Настройване на GitLab CI за качване на java проект в maven central
Тази статия е предназначена за разработчици на Java, които трябва бързо да публикуват своите продукти в централните хранилища на sonatype и/или maven с помощта на GitLab. В тази статия ще говоря за настройването на gitlab-runner, gitlab-ci и maven-plugin за решаване на този проблем.
Предпоставки:
Безопасно съхранение на mvn и GPG ключове.
Сигурно изпълнение на публични CI задачи.
Качване на артефакти (версия/моментна снимка) в публични хранилища.
Автоматична проверка на версиите за публикуване в maven central.
Общо решение за качване на артефакти в хранилище за множество проекти.
Подробно описание на механизма за публикуване на артефакти в Maven Central чрез Sonatype OSS Repository Hosting Service вече е описано в тази статия потребител гуголплекс, така че ще препращам към тази статия на правилните места.
Предварителна регистрация на Sonatype JIRA и стартирайте билет за отваряне на хранилището (за повече подробности прочетете раздела Създайте билет за Sonatype JIRA). След отваряне на хранилището двойката потребителско име/парола на JIRA (наричана по-долу акаунт на Sonatype) ще се използва за качване на артефакти в Nexus на Sonatype.
Ако използвате Linux конзолата за генериране на GPG ключ (gnupg/gnupg2), тогава трябва да инсталирате RNG инструменти за генериране на ентропия. В противен случай генерирането на ключ може да отнеме много време.
На първо място, трябва да създадете и конфигурирате проект, в който тръбопроводът ще се съхранява за внедряване на артефакти. Нарекох проекта си просто и неусложнено - разположи
След като създадете хранилището, трябва да ограничите достъпа, за да промените хранилището.
Отидете на проекта -> Настройки -> Хранилище -> Защитени клонове. Ние изтриваме всички правила и добавяме едно правило със заместващ знак * с право на натискане и сливане само за потребители с ролята на поддържащи. Това правило ще работи за всички потребители както на този проект, така и на групата, към която този проект принадлежи.
Ако има няколко поддържащи, тогава най-доброто решение би било да се ограничи достъпът до проекта по принцип.
Отидете на проекта -> Настройки -> Общи -> Видимост, функции на проекта, разрешения и задайте Видимост на проекта на частен.
Имам проект в публичен достъп, тъй като използвам собствения си GitLab Runner и само аз имам достъп да променям хранилището. Е, всъщност не е в мой интерес да показвам лична информация в публичните регистрационни файлове на тръбопровода.
Затягане на правилата за промяна на хранилището
Отидете на проекта -> Настройки -> Хранилище -> Push Rules и задайте флаговете Committer restriction, Проверете дали авторът е потребител на GitLab. Аз също препоръчвам настройка ангажирам подписванеи задайте флага за отхвърляне на неподписани ангажименти.
След това трябва да конфигурирате тригер за изпълнение на задачи
Отидете на проект -> Настройки -> CI / CD -> Задействания на тръбопровода и създайте нов тригер-токен
Този токен може незабавно да бъде добавен към общата конфигурация на променливите за група проекти.
Отидете в групата -> Настройки -> CI / CD -> Променливи и добавете променлива DEPLOY_TOKEN с trigger-token в стойността.
Този раздел описва конфигурацията за изпълнение на задачи при разгръщане с помощта на родния (специфичен) и публичен (споделен) инструмент за изпълнение.
Конкретен бегач
Използвам собствени бегачи, защото преди всичко е удобно, бързо, евтино.
За runner препоръчвам Linux VDS с 1 CPU, 2 GB RAM, 20 GB HDD. Емисионна цена ~ 3000₽ на година.
Моят бегач
За бегача взех VDS 4 CPU, 4 GB RAM, 50 GB SSD. Струва ~11000₽ и никога не съжалявам.
Имам общо 7 машини. 5 на аруба и 2 на ihor.
И така, имаме бегач. Сега ще го настроим.
Отиваме до машината през SSH и инсталираме java, git, maven, gnupg2.
Създайте директория за кеша на maven и задайте групови права runner
Можете да пропуснете тази стъпка, ако не планирате да стартирате няколко бегача на една и съща машина.
Runtime platform arch=amd64 os=linux pid=17594 revision=3001a600 version=11.10.0
Running in system-mode.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab.com/
Please enter the gitlab-ci token for this runner:
REGISTRATION_TOKEN
Please enter the gitlab-ci description for this runner:
[ih1174328.vds.myihor.ru]: Deploy Runner
Please enter the gitlab-ci tags for this runner (comma separated):
deploy
Registering runner... succeeded runner=ZvKdjJhx
Please enter the executor: docker-ssh, parallels, virtualbox, docker-ssh+machine, kubernetes, docker, ssh, docker+machine, shell:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Проверете дали бегачът е регистриран. Отидете на gitlab.com -> deploy-project -> Settings -> CI/CD -> Runners -> Specific Runners -> Runners, активирани за този проект
Ние генерираме ключ, като отговаряме на въпроси. Използвах собственото си име и имейл.
Не забравяйте да посочите паролата за ключа. Артефактите ще бъдат подписвани с този ключ.
gpg --gen-key
проверите
gpg --list-keys -a
/home/gitlab-deployer/.gnupg/pubring.gpg
----------------------------------------
pub 4096R/00000000 2019-04-19
uid Petruha Petrov <[email protected]>
sub 4096R/11111111 2019-04-19
Качване на нашия публичен ключ на сървъра за ключове
gpg --keyserver keys.gnupg.net --send-key 00000000
gpg: sending key 00000000 to hkp server keys.gnupg.net
Създайте директория maven хранилище и връзка с кеша (не правете грешка)
Тази стъпка може да се пропусне, ако не планирате да стартирате няколко бегача на една и съща машина.
Добавете файла .gitlab-ci.yml към корена на проекта за разгръщане
Скриптът представя две взаимно изключващи се задачи за внедряване. Конкретен бегач или съответно споделен бегач.
.gitlab-ci.yml
stages:
- deploy
Specific Runner:
extends: .java_deploy_template
# Задача будет выполняться на вашем shell-раннере
tags:
- deploy
Shared Runner:
extends: .java_deploy_template
# Задача будет выполняться на публичном docker-раннере
tags:
- docker
# Образ из раздела GitLab Runner -> Shared Runner -> Docker
image: registry.gitlab.com/group/deploy-project:latest
before_script:
# Импортируем GPG ключ
- printf "${GPG_SECRET_KEY}" | gpg --batch --import
# Сохраняем maven конфигурацию
- printf "${SETTINGS_SECURITY_XML}" > ~/.m2/settings-security.xml
- printf "${SETTINGS_XML}" > ~/.m2/settings.xml
.java_deploy_template:
stage: deploy
# Задача сработает по триггеру, если передана переменная DEPLOY со значением java
only:
variables:
- $DEPLOY == "java"
variables:
# отключаем клонирование текущего проекта
GIT_STRATEGY: none
script:
# Предоставляем возможность хранения пароля в незашифрованном виде
- git config --global credential.helper store
# Сохраняем временные креды пользователя gitlab-ci-token
# Токен работает для всех публичных проектов gitlab.com и для проектов группы
- echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
# Полностью чистим текущую директорию
- rm -rf .* *
# Клонируем проект который, будем деплоить в Sonatype Nexus
- git clone ${DEPLOY_CI_REPOSITORY_URL} .
# Переключаемся на нужный коммит
- git checkout ${DEPLOY_CI_COMMIT_SHA} -f
# Если хоть один pom.xml содержит параметр autoReleaseAfterClose валим сборку.
# В противном случае есть риск залить сырые артефакты в maven central
- >
for pom in $(find . -name pom.xml); do
if [[ $(grep -q autoReleaseAfterClose "$pom" && echo $?) == 0 ]]; then
echo "File $pom contains prohibited setting: <autoReleaseAfterClose>";
exit 1;
fi;
done
# Если параметр DEPLOY_CI_COMMIT_TAG пустой, то принудительно ставим SNAPSHOT-версию
- >
if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then
mvn versions:set -DnewVersion=${DEPLOY_CI_COMMIT_TAG}
else
VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
if [[ "${VERSION}" == *-SNAPSHOT ]]; then
mvn versions:set -DnewVersion=${VERSION}
else
mvn versions:set -DnewVersion=${VERSION}-SNAPSHOT
fi
fi
# Запускаем задачу на сборку и деплой артефактов
- mvn clean deploy -DskipTests=true
Ако имате многомодулен проект и не е необходимо да качвате конкретен модул в хранилището, тогава трябва да добавите към pom.xml на този модул nexus-staging-maven-plugin със знаме skipNexusStagingDeployMojo
След качване на моментна снимка/издание версиите са налични в сценични хранилища
<repositories>
<repository>
<id>SonatypeNexus</id>
<url>https://oss.sonatype.org/content/groups/staging/</url>
<!-- Не надо указывать флаги snapshot/release для репозитория -->
</repository>
</repositories>
Още плюсове
Много богат списък от цели за работа с хранилището на nexus (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
Автоматична проверка за изтегляне за изтегляне в maven central
Когато маркерът е зададен, съответната задача в проекта за внедряване се задейства автоматично, за да качи версията на изданието в nexus (пример).
Най-добрата част е, че затвореното освобождаване автоматично се задейства в nexus.
[INFO] Performing remote staging...
[INFO]
[INFO] * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO] * Created staging repository with ID "orgtouchbit-1037".
[INFO] * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1037
[INFO] * Uploading locally staged artifacts to profile org.touchbit
[INFO] * Upload of locally staged artifacts finished.
[INFO] * Closing staging repository with ID "orgtouchbit-1037".
Waiting for operation to complete...
.........
[INFO] Remote staged 1 repositories, finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Shields4J 1.0.0 .................................... SUCCESS [ 9.603 s]
[INFO] test-core .......................................... SUCCESS [ 3.419 s]
[INFO] Shields4J client ................................... SUCCESS [ 9.793 s]
[INFO] TestNG listener 1.0.0 .............................. SUCCESS [01:23 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:47 min
[INFO] Finished at: 2019-04-21T04:05:46+03:00
[INFO] ------------------------------------------------------------------------
И ако нещо се обърка, тогава задачата ще се провали
[INFO] Performing remote staging...
[INFO]
[INFO] * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO] * Created staging repository with ID "orgtouchbit-1038".
[INFO] * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1038
[INFO] * Uploading locally staged artifacts to profile org.touchbit
[INFO] * Upload of locally staged artifacts finished.
[INFO] * Closing staging repository with ID "orgtouchbit-1038".
Waiting for operation to complete...
.......
[ERROR] Rule failure while trying to close staging repository with ID "orgtouchbit-1039".
[ERROR]
[ERROR] Nexus Staging Rules Failure Report
[ERROR] ==================================
[ERROR]
[ERROR] Repository "orgtouchbit-1039" failures
[ERROR] Rule "signature-staging" failures
[ERROR] * No public key: Key with id: (1f42b618d1cbe1b5) was not able to be located on <a href=http://keys.gnupg.net:11371/>http://keys.gnupg.net:11371/</a>. Upload your public key and try the operation again.
...
[ERROR] Cleaning up local stage directory after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR] * Deleting context 9043b43f77dcc9.properties
[ERROR] Cleaning up remote stage repositories after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR] * Dropping failed staging repository with ID "orgtouchbit-1039" (Rule failure during close of staging repositories: [orgtouchbit-1039]).
[ERROR] Remote staging finished with a failure: Staging rules failure!
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Shields4J 1.0.0 .................................... SUCCESS [ 4.073 s]
[INFO] test-core .......................................... SUCCESS [ 2.788 s]
[INFO] Shields4J client ................................... SUCCESS [ 3.962 s]
[INFO] TestNG listener 1.0.0 .............................. FAILURE [01:07 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
В резултат на това ни остава само един избор. Или изтрийте тази версия или публикувайте.
След освобождаването, след известно време, артефактите ще бъдат вътре
извън темата
За мен беше откровение, че maven индексира други публични хранилища.
Трябваше да кача robots.txt, защото индексира старото ми хранилище.
Отделен проект за внедряване, в който можете да реализирате няколко CI задачи за качване на артефакти в публични хранилища за различни езици за разработка.
Проектът за внедряване е изолиран от външна намеса и може да бъде модифициран само от потребители с роли на собственик и поддържащ.
Отделен специфичен Runner с „горещ“ кеш за изпълнение само на задачи за разгръщане.
Публикуване на моментни снимки/релиз версии в публично хранилище.
Автоматична проверка на версията на изданието за готовност за публикуване в maven central.
Защита срещу автоматично публикуване на „сурови“ версии в maven central.
Създавайте и публикувайте версии на моментни снимки „при щракване“.
Единично хранилище за получаване на моментни снимки/релиз версии.
Обща линия за изграждане / тестване / публикуване на java проект.
Настройката на GitLab CI не е толкова сложна тема, колкото изглежда на пръв поглед. Достатъчно е да настроите CI до ключ няколко пъти и сега далеч не сте аматьор по този въпрос. Освен това документацията на GitLab е много излишна. Не се страхувайте да направите първата крачка. Пътят се появява под стъпките на човека, който върви (не помня кой го каза :)
Ще се радвам на обратна връзка.
В следващата статия ще ви покажа как да настроите GitLab CI за конкурентно изпълнение на тестови задачи за интеграция (извършване на тестови услуги с docker-compose), ако имате само един shell runner.