Gitlab CI: git tag и исключение из pipeline

Введение

Тэги в git используется для фиксирования каких-либо изменений. Как правило, данная функциональность применяется для версионирования. В данной заметке будет рассмотрена настройка pipeline Gitlab CI, в котором выполняется тэгирование версии разработанного кода напрямую из pipeline.

Примеры будут выполняться на базе приложения, написанного на NodeJS. В корне репозитория располагается файл package.json, в котором вручную указывается версия разрабатываемого приложения – эта версия и будет служить в качестве тэга.

Схема работы

  • Изменения отправляются в ветку master\main, срабатывает pipeline
  • На сервере с gitlub-runner выполняется клонирование репозитория в домашнюю директорию gitlab-runner
  • Из package.json считывается версия, фиксируется в файле variables.txt как артефакт для возможности передачи сведений в следующие стадии
  • Локально создаётся тэг и пушится в Gitlab

Одной из проблем, с которой придётся столкнуться при выполнении данной задачи, является вызов pipeline из pipeline при выполнении команды git tag. Возможные решения этой проблемы будут описаны ниже.

Реализация

В веб-интерфейсе Gitlab необходимо пользователя, добавить его в проект, и создать токен пользователю с правами на чтение\запись через API. После создать переменную, содержащую токен, по пути Settings->CI\CD->Variables с токеном. Важно не забыть обеспечить минимальную приватность переменной, поставив галку Mask variable:

В .gitlab-ci.yaml используется следующий код:

check_version:
  stage: check_version
  artifacts: 
    paths:
      - vars.txt
    expire_in: 1 week
  before_script:
    - echo export APP_VERSION=$(node -p "require('./package.json').version")  >> vars.txt
    - echo export APP_NAME="${CI_PROJECT_NAME}" >> vars.txt
    - source vars.txt
  script:
    - "git config --global user.email 'robot@domain.ru'"
    - "git config --global user.name 'robot'"
    - "git remote set-url origin https://oauth2:${CI_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git" 
    - >
       if [ $(git tag -l v"${APP_VERSION}") ]; then
           echo "Tag for v${APP_VERSION} already exists, increment version number" && exit 1
        else
            echo "Create tag v${APP_VERSION}"
            git tag -a v${APP_VERSION} -m ${CI_COMMIT_SHA}
            git push -o ci.skip origin v${APP_VERSION}
        fi
  rules:
    - if: "$CI_COMMIT_REF_NAME == 'master' && $CI_PIPELINE_SOURCE != 'merge_request_event'"

Небольшое пояснение:

  • В блоке before_script парсится версия приложения и отправляется в артефакт vars.txt. Туда же отправляется имя репозитория из встроенной переменной Gitlab CI. В дальнейшем этот артефакт подключается в других job.
  • В блоке script опять же из встроенных переменных Gitlab CI формируется удаленный репозиторий в .git/config, проверяется наличие уже созданного тэга во избежание ошибок
  • Создание тэга выполняется через простую команду git tag, но используется конструкция -o skip.ci – это фича git версии 2+, которая формирует переменные, а Gitlab CI их перехватывает и тем самым в данном месте не триггерится новый pipeline

Заключение

Рассмотрен простой вариант создания тэга в gitlab CI. Существует несколько возможностей реализации, git tag – самая простейшая из имеющихся, но также есть возможность тэгирования через API гитлаба. Например, так:

curl -X POST --silent "${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/repository/tags?tag_name=${APP_VERSION}&ref=${CI_COMMIT_SHA}&private_token=${CI_TOKEN}"
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: