Автоматическая публикация npm пакета из gitlab ci/cd

Автоматическая публикация npm пакета из gitlab ci/cd


Всем привет! Сегодня я расскажу как реализовать автоматическую публикацию npm пакета в cicd gitlab, с помощью каких инструментов мы генерируем CHANGELOG файл и обновляем версию package.json. А так же как публикуем изменения в gitlab репозитории.

Я постараюсь дать вам простую инструкцию, расскажу с какими сложностями мы столкнулись и как их решили.

Задача

  • Настроить ci/cd таким образом, чтобы новая версия npm пакета автоматически публиковалась в реестре пакетов при изменении master ветки в git репозитории.
  • Автоматически определить следующий номер версии npm пакета
  • Сгенерировать CHANGELOG.md файл
  • Опубликовать изменения в gitlab репозитории
  • Опубликовать пакет в реестре npm пакетов

Реализация:

Давайте посмотрим на результат и разберем код более подробно


# .gitlab-ci.yml
image: "node:16-slim"

stages:
 - publish

publish:
 stage: publish
 variables:
     GIT_STRATEGY: clone
 before_script:
  - apt-get update && apt-get install git -y
 script:
  # Конфигурация npm
  - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
  
    # Конфигурация git
  - git config --global user.email "${GIT_USER_EMAIL}"
  - git config --global user.name "${GIT_USER_NAME}"

  # Установка зависимостей и сборка проекта
  - yarn
  - yarn build

  # Определение новой версии npm пакета и генерация CHANGELOG.md файла
  - yarn standard-version
  - commitMessage=$(git log -1 --pretty=%B)
  - tagname=$(git tag --points-at HEAD)
  - version=${tagname:1}

  # Решение проблемы с циклическим вызовом
  - git tag -d $tagname
  - git commit --amend -m "[ci skip] ${commitMessage}" --no-verify
  - git tag -a $tagname -m ''

  # Публикация в gitlab
  - git push <https://${GIT_SYNC_USER}:${GIT_SYNC_TOKEN}@git.nlmk.com/$CI_PROJECT_PATH.git> --follow-tags master:master

  # Публикация в npm
  - yarn publish --new-version $version --verbose

 only:
  - master

Для публикации пакета в npm и для отправки коммита в репозиторий нам требуется настроить конфигурацию для npm и git, а так же установить зависимости проекта.

Опубликовать пакет в npm репозитории можно c помощью авторизованного пользователи, либо с применением accessToken. Использование accessToken в ci/cd более предпочтительный вариант, потому что вам не придется хранить логин и пароль пользователя в переменных gitlab.

Конфигурация npm:

# Конфигурация npm
- echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc

NPM_TOKEN - имя ci переменной, в которой хранится npm токен

Более подробно про access tokens в npm можно прочитать в документации.

Более подробно ознакомиться с gitlab переменными можно здесь

Конфигурация git:

Для конфигурации git пользователя мы используем технического пользователя, чьё имя и email хранятся в ci переменных:


# Конфигурация git
- git config --global user.email "${GIT_USER_EMAIL}"
- git config --global user.name "${GIT_USER_NAME}"

GIT_USER_EMAIL GIT_USER_NAME- имя ci переменной, в которой хранится имя и email git пользователя, от которого будет создаваться коммит (В нашем случае это специальный технический пользователь)

Установка зависимостей и сборка проекта

С установкой зависимостей и сборкой проекта все просто:


# Установка зависимостей и сборка проекта
- yarn
- yarn build

Данные команды установят зависимости и соберут наш проект.

Определение новой версии npm пакета и генерация CHANGELOG.md файла

Для генерации CHANGELOG файла мы используем библиотеку standard-version.

При запуске команды standard-version происходит следующее:

  • Вычисляется новая версия npm пакета в соответствие с conventional commit и semver
  • Обновляется версия пакета в package.json
  • Обновляется CHANGELOG.md файл
  • Создается тег указывающий на новую версию (напримерv1.13.2)
  • Создается коммит с изменениями (текст коммитаchore(release): 1.13.2)
# Определение новой версии npm пакета и генерация CHANGELOG.md файла
- yarn standard-version
- commitMessage=$(git log -1 --pretty=%B)
- tagname=$(git tag --points-at HEAD)
- version=${tagname:1}

После выполнения команды standard-version я сохраняю в переменных сообщение созданного коммита commitMessage (chore(release): 1.13.2), имя созданного тега tagname (v1.13.2) и номер новой версии пакета: version (1.13.2) Они понадобятся нам позже

Решение проблемы с циклическим вызовом

После обновления версии пакета нам требуется вылить наши изменения в git, но есть одна маленькая проблема: если мы просто опубликуем новую версию в git и обновим master ветку то запустится новый pipeline и так далее, по бесконеному циклу. чтобы этого не происходило коммит должен начинаться с [ci-skip]. Для того, чтобы решить эту проблему, следует изменить текст созданного коммита, и не забыть про теги.


# Решение проблемы с циклическим вызовом
# Удаляем поседний созданный тег
- git tag -d $tagname

# Добавляем [ci-skip] в последний коммит
git commit --amend -m "[ci skip] ${commitMessage}" --no-verify

# Создаем новый тег на последнем коммите
git tag -a $tagname -m ''

Как вы можете заметить я удаляю тег, меняю сообщение коммита и снова добавляю тег.

Если мы просто попытаемся изменить сообщение коммита с помощью команды - git commit --amend то будет создан новый коммит. Такое поведение связано с тем, что к изменяемому коммиту привязан тег. Чтобы решить эту проблему мы удаляем тег, далее меняем сообщение коммита, а потом создаем тег на измененном коммите.

Публикация в gitlab:

Для обновления кодовой базы нам требуется внести изменения в master ветке.


# Публикация в gitlab
- git push <https://${GIT_SYNC_USER}:${GIT_SYNC_TOKEN}@git.nlmk.com/$CI_PROJECT_PATH.git> --follow-tags master:master

GIT_SYNC_USER - имя пользователя, которое будет указано в коммите

GIT_SYNC_TOKEN - gitlab токен технического пользователя. Более подробно про gitlab токены можно прочитать тут)

CI_PROJECT_PATH - предопределенная переменная, в которой хранится path проекта с включенным именем проекта. Более подробно со списком доступных переменных можно ознакомиться в документации

Публикация в npm

# Публикация в npm
- yarn publish --new-version $version --verbose

При публикации пакета используется переменная $version, в которой сохранена новая версия пакета. Мы явно указываем с какой версией требуется опубликовать npm пакет.

CI/CD переменные

NPM_TOKEN - npm токен.

GIT_USER_EMAIL - email технического пользователя gitlab

GIT_USER_NAME - username технического пользователя gitlab

GIT_SYNC_USER - имя пользователя, которое будет указано в коммите

GIT_SYNC_TOKEN - gitlab токен технического пользователя

CI_PROJECT_PATH - path проекта с включенным именем проекта



Ссылки по теме:

Gitlab CI/CD variables

Gitlab access tokens

Standart-version utility

Semver

Conventional Commits

Predefined Gitlab variables reference



Report Page