Configurazione di GitLab CI per carica un prughjettu java à Maven Central
Questu articulu hè destinatu à i sviluppatori java chì anu bisognu di pubblicà rapidamente i so prudutti à i repositori centrali di sonatype è / o maven cù GitLab. In questu articulu, parleraghju di a creazione di gitlab-runner, gitlab-ci è maven-plugin per risolve stu prublema.
Prerequisiti:
Archiviazione sicura di e chjave mvn è GPG.
Esecuzione sicura di i travaglii CI publichi.
Caricà artefatti (release / snapshot) à i repositori publichi.
Verificazione automatica di e versioni di liberazione per a publicazione in Maven Central.
Una soluzione generale per a carica di artefatti in un repository per parechji prughjetti.
Una descrizzione dettagliata di u mecanismu per a publicazione di artefatti à Maven Central via u Sonatype OSS Repository Hosting Service hè digià descritta in stu articulu utilizatore Googlelplex, cusì mi riferiraghju à questu articulu in i posti ghjusti.
Pre-registru à Sonatype JIRA è cuminciate un bigliettu per apre u repository (per più dettagli, leghjite a sezione Crea un bigliettu Sonatype JIRA). Dopu avè apertu u repository, a coppia di login/password JIRA (da quì in seguitu chjamatu u contu Sonatype) serà utilizata per carricà artefatti à u nexus Sonatype.
Sè vo aduprate a cunsola Linux per generà una chjave GPG (gnupg/gnupg2), allora avete bisognu di stallà rng-tools per generà entropia. Altrimenti, a generazione di chjave pò piglià assai tempu.
Configurazione di un prughjettu di implementazione in GitLab
Prima di tuttu, avete bisognu di creà è cunfigurà un prughjettu in u quale u pipeline serà guardatu per a distribuzione di artefatti. Aghju chjamatu u mo prughjettu simplice è senza complicazioni - sparghje
Dopu avè creatu u repository, avete bisognu di restringe l'accessu per cambià u repository.
Andà à u prughjettu -> Settings -> Repository -> Prutetti Branches. Sguassate tutte e regule è aghjunghje una sola regula cù Wildcard * cù u dirittu di spinghja è unisce solu per l'utilizatori cù u rolu di Maintainers. Sta regula hà da travaglià per tutti l'utilizatori di stu prughjettu è di u gruppu à quale stu prughjettu appartene.
Se ci sò parechji mantene, allora a megliu suluzione seria di limità l'accessu à u prugettu in principiu.
Andà à u prughjettu -> Settings -> General -> Visibilità, funziunalità di u prugettu, permessi è stabilisce a visibilità di u prugettu à Private.
Aghju un prughjettu in accessu publicu, postu chì aghju utilizatu u mo propiu GitLab Runner è solu aghju accessu per mudificà u repository. Ebbè, in realtà ùn hè micca in u mo interessu di mostrà infurmazione privata in logs di pipeline publicu.
Stringhjendu e regule per cambià u repository
Andà à u prugettu -> Configurazione -> Repository -> Push Rules è stabilisce e bandiere Restrizzione di u Committer, Verificate se l'autore hè un utilizatore GitLab. Mi cunsigliu ancu di mette firma di impegni, è stabilisce a bandiera Reject unsigned commits.
In seguitu, avete bisognu di cunfigurà un trigger per eseguisce e attività
Andà à u prugettu -> Settings -> CI / CD -> Pipeline triggers è crea un novu trigger-token
Stu token pò esse aghjuntu immediatamente à a cunfigurazione generale di variàbili per un gruppu di prughjetti.
Andà à u gruppu -> Settings -> CI / CD -> Variables è aghjunghje una variabile DEPLOY_TOKEN cù trigger-token in u valore.
Questa sezione descrive a cunfigurazione per eseguisce e attività nantu à a distribuzione utilizendu u corridore nativu (Specificu) è publicu (Shared).
Runner specificu
Aghju utilizatu i mo corridori, perchè prima di tuttu hè convenientu, veloce, economicu.
Per i corridori, ricumandemu Linux VDS cù 1 CPU, 2 GB RAM, 20 GB HDD. Prezzo di emissione ~ 3000₽ annu.
U mo corridore
Per u corridore aghju pigliatu VDS 4 CPU, 4 GB RAM, 50 GB SSD. Custa ~ 11000 ₽ è ùn si dispiace mai.
Aghju un totale di 7 macchine. 5 in aruba è 2 in ihor.
Dunque, avemu un corridore. Avà l'avemu stallatu.
Andemu à a macchina via SSH è installate java, git, maven, gnupg2.
Crea un repertoriu per a cache di Maven è attribuisce diritti di gruppu runner
Pudete saltà stu passu se ùn avete micca pensatu à eseguisce parechji corridori nantu à a stessa macchina.
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!
Verificate chì u corridore hè registratu. Andà à gitlab.com -> deploy-project -> Settings -> CI/CD -> Runners -> Specific Runners -> Runners attivati per stu prughjettu
Generemu una chjave rispondendu à e dumande. Aghju utilizatu u mo propiu nome è email.
Assicuratevi di specificà a password per a chjave. L'artefatti seranu firmati cù sta chjave.
gpg --gen-key
Verificendu
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
Caricà a nostra chjave publica à u keyserver
gpg --keyserver keys.gnupg.net --send-key 00000000
gpg: sending key 00000000 to hkp server keys.gnupg.net
Crea un annuariu Maven ripositoriu è ligà cù a cache (ùn fate micca sbagliu)
Stu passu pò esse saltatu sè ùn avete micca pensatu à eseguisce parechji corridori nantu à a stessa macchina.
Creemu un Dockerfile abbastanza simplice per eseguisce e attività nantu à a distribuzione cù a versione desiderata di Java. Quì sottu hè un esempiu per alpine.
FROM java:8u111-jdk-alpine
RUN apk add gnupg maven git --update-cache
--repository http://dl-4.alpinelinux.org/alpine/edge/community/ --allow-untrusted &&
mkdir ~/.m2/
Aghjunghjite u schedariu .gitlab-ci.yml à a radica di u prugettu di implementazione
U script presenta dui compiti di implementazione mutuamente esclusivi. Corridore specificu o Corridore spartutu rispettivamente.
.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
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<!-- Генерация javadoc должна быть после фазы генерации ресурсов -->
<phase>prepare-package</phase>
<configuration>
<!-- Очень помогает в публичных проектах -->
<failOnError>true</failOnError>
<failOnWarnings>true</failOnWarnings>
<!-- Убирает ошибку поиска документации в target директории -->
<detectOfflineLinks>false</detectOfflineLinks>
</configuration>
</execution>
</executions>
</plugin>
Sì avete un modulu chì ùn cuntene micca java (per esempiu solu risorse)
O ùn vulete micca generà javadoc in principiu, allora per aiutà maven-jar-plugin
Se tenete un prughjettu multi-modulu, è ùn avete micca bisognu di carricà un modulu specificu à u repository, allora avete bisognu di aghjunghje à u pom.xml di stu modulu. nexus-staging-maven-plugin cù bandiera skipNexusStagingDeployMojo
Dopu avè caricatu e versioni di snapshot / release sò dispunibili in staging repository
<repositories>
<repository>
<id>SonatypeNexus</id>
<url>https://oss.sonatype.org/content/groups/staging/</url>
<!-- Не надо указывать флаги snapshot/release для репозитория -->
</repository>
</repositories>
Più plus
Una lista assai ricca di miri per travaglià cù u repository nexus (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
Verificazione di liberazione automatica per a scaricabilità in Maven Central
Quandu u tag hè stabilitu, u compitu currispundente in u prughjettu di implementazione hè attivatu automaticamente per carica a versione di liberazione in nexus (esempiu).
A più bona parte hè chì a liberazione vicinu attiva automaticamente in 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] ------------------------------------------------------------------------
È s'è qualcosa andò male, allora u compitu fallerà
[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] ------------------------------------------------------------------------
Per via di u risultatu, ci hè una sola scelta. O sguassate sta versione o publicate.
Dopu à a liberazione, dopu qualchì tempu, l'artefatti seranu in
offtopic
Hè stata una rivelazione per mè chì Maven indexa altri repositori publichi.
Aviu avutu a carica di robots.txt perchè hà indexatu u mo vechju repository.
Un prughjettu di implementazione separatu in u quale pudete implementà parechje attività CI per a carica di artefatti à i repositori publichi per diverse lingue di sviluppu.
U prughjettu di implementazione hè isolatu da l'interferenza esterna è pò esse mudificatu solu da l'utilizatori cù i roli di u pruprietariu è di u mantenimentu.
Un corridore specificu separatu cù una cache "calda" per eseguisce solu attività di implementazione.
Publicazione di versioni snapshot/release in un repositoriu publicu.
Verificazione automatica di a versione di liberazione per a preparazione per a publicazione in Maven Central.
Prutezzione contr'à a publicazione automatica di versioni "crue" in Maven Central.
Custruite è pubblicà versioni snapshot "à cliccà".
Repositoriu unicu per uttene versioni di snapshot / rilascio.
Pipeline generale per custruisce / pruvà / publicà un prughjettu java.
L'installazione di GitLab CI ùn hè micca un tema cusì complicatu cum'è pare à prima vista. Hè abbastanza à stallà CI nantu à una basa turnkey un paru di volte, è avà site luntanu da un dilettante in questa materia. Inoltre, a documentazione di GitLab hè assai redundante. Ùn àbbia paura di fà u primu passu. A strada si prisenta sottu à i passi di a persona chì cammina (ùn mi ricordu micca chì l'hà dettu :)
Seraghju felice di feedback.
In u prossimu articulu, vi mustraraghju cumu cunfigurà GitLab CI per eseguisce e funzioni di teste di integrazione in modu competitivu (eseguisce servizii di prova cù docker-compose) se avete solu un shell runner.