Перейти к содержанию

Pipeline


Типы pipeline

Gitlab merge request pipeline

Merge request pipelines

Описание

Запускается в момент создания merge requests. Обычно используется для проверяющего merge requests чтобы определить тесты кода прошли успешно или нет

Условия запуска pipeline:

  • в CI/CD указан rules CI_PIPELINE_SOURCE == "merge_request_event"
  • у вас есть права Developer, Maintainer or Owner роль

.gitlab-ci.yml

stages:
 - test


testyrovanie:
 stage: test
 script:
  - echo "test"
 rules:
  - if: $CI_PIPELINE_SOURCE == "merge_request_event"
 tags:
  - shell


Пример с child pipeline

.gitlab-ci.yml

stages:
 - test
 - build
 - trigger


django tests:
 image: python:3.9-alpine 
 stage: test
 script:
  - pip install -r requirements.txt
  - mkdir db
  - python manage.py test
 tags:
  - docker_test


build docker:
 stage: build
 image: docker:stable
 services:
  - docker:dind
 variables:
  DOCKER_HOST: tcp://docker:2375/
  DOCKER_TLS_CERTDIR: "" 
 script:
  - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
  - docker build -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} .
  - if [[ "${CI_COMMIT_BRANCH}" == "${CI_DEFAULT_BRANCH}" ]] ; then 
        docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY_IMAGE}:latest;
        docker push ${CI_REGISTRY_IMAGE}:latest; fi
  - if [[ -z "${CI_COMMIT_TAG}" ]] ; then 
        docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG};
    else
        docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG};
        docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}; fi 
 needs: 
  - ["django tests"]
 tags: 
  - docker_test

start cd pipeline:
 stage: trigger
 trigger:
  include:
   - local: .gitlab/deploy.yml
  strategy: depend

.gitlab/deploy.md

stages:
 - deploy

deploy to prod:
 stage: deploy
 script: 
  - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
  - docker pull ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
  - docker rm -f ${CI_PROJECT_NAME} || true
  - docker run --name ${CI_PROJECT_NAME} -d -p 80:8000 -v db:/app/db ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
 tags: 
  - shell

результат

результат child pipeline

Пример production pipeline

.gitlab-ci.yml

stages:
 - build
 - deploy


build_image:
 image: docker:29.0.1-cli
 services:
  - docker:29.0.1-dind
 variables:
  DOCKER_HOST: tcp://docker:2375
  DOCKER_TLS_CERTDIR: ""
 stage: build
 script:
  - echo "$CI_REGISTRY_PASSWORD" |
    docker login
    --username "$CI_REGISTRY_USER"
    --password-stdin
    "$CI_REGISTRY"
  - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
  - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
 tags:
  - docker_test

deploy_compose:
 stage: deploy
 resource_group: production
 needs: 
  - build_image
 variables:
  IMAGE_TAG: "$CI_COMMIT_SHA"
 before_script:
  - docker info
  - echo "$CI_REGISTRY_PASSWORD" |
    docker login
    --username "$CI_REGISTRY_USER"
    --password-stdin
    "$CI_REGISTRY" 
 script:
  - |
    TOKEN=$CI_JOB_TOKEN
    ssh "$PROD_USER@$PROD_HOST" \
    "docker login \
    -u '$CI_REGISTRY_USER' \
    -p '$TOKEN' \
    '$CI_REGISTRY'"
  - |
    scp -r * $PROD_USER@$PROD_HOST:/opt/nginx/
    ssh "$PROD_USER@$PROD_HOST" "
      cd /opt/nginx
      cd for_test
      docker compose pull
      docker compose up -d
    "
 rules:
  - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    when: manual
 tags:
  - shell
структура production pipeline

Rules

Ручной запуск deply на PROD

Пример файла .gitlab-ci.yml

deploy to prod:
 stage: deploy
 script: 
  - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
  - docker pull ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
  - docker rm -f ${CI_PROJECT_NAME} || true
  - docker run --name ${CI_PROJECT_NAME} -d -p 80:8000 -v db:/app/db ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
 rules:
  - when: manual
 tags: 
  - shell
pipeline run manual

Правила для запуска по определенной ветке

Используется когда вам нужно запускать pipeline при коммите в определенную ветку

Пример 1:

stages:
 - primer

rules_on_one_job:
 stage: primer
 script:
  - |
    if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then
     echo "Pipeline run for head branch"
    elif [ "$CI_COMMIT_BRANCH" = "devel" ]; then
     echo "Pipeline run for branch: devel"
    else
     echo "Pipeline run for other branch: $CI_COMMIT_BRANCH"
    fi
 tags:
  - shell

Пример 2:

stages:
 - primer
 - primer_sec

rules_branch:
 stage: primer
 script:
  - echo "run job commit in main branch"
 rules:
  - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' 
 tags:
  - shell

rules_2_branch:
 stage: primer_sec
 script: 
  - echo "run job commit in '$CI_COMMIT_BRANCH' branch"
 rules:
  - if: '$CI_COMMIT_BRANCH == "devel"'
 tags: 
  - shell

Запуск по тегу

Запускается только когда есть Tag

Пример файла .gitlab-ci.yml

stages:
 - debug

rules_on_one_job:
 stage: debug
 script:
  - echo "create tag"
 rules:
  - if: '$CI_COMMIT_TAG'
 tags: 
  - shell

Resource group

GitLab resource group

Описание

механизм GitLab, который не позволяет двум job одновременно работать с одним ресурсом.

Используется для операций, изменяющих состояние инфраструктуры (deploy, миграции БД, terraform, обновление серверов, ...).

Не применяется для независимых задач (bild, test, lint, анализ кода, ...), которые могут выполняться безопасно параллельно.

Ресурсом может быть:

  • production сервер
  • staging сервер
  • кастер Kubernetes
  • любое окружение которое нельзя одновременно изменять.

Когда используется:

  • когда нужно защитить ресурсы от параллельного выполнения одной и той же job.

Пример:

deploy:
  stage: deploy
  resource_group: production
  script:
    - docker compose pull
    - docker compose up -d

Что получается?

  • теперь даже если кто-то одновременно с вами запушит свой код и оба pipeline запустятся одновременно, то ранняя job будет выполняться, а вторая будет ждать пока освободятся ресурсы

в итоге вторая job встает на паузу с сообщением: Waiting for resource

а как же manual?

manual не защищает от одновременного выполнения, так как если вы обе job запустите вручную, без resource_group они будут работать параллельно.

Какие бывают resource_group?

название может быть любое (по желанию разработчика).

Главное правило: один resource_group = один ресурс, который нельзя изменять одновременно.