Opsætning af GitLab CI til at uploade et java-projekt til maven central
Denne artikel er beregnet til java-udviklere, der hurtigt har brug for at udgive deres produkter til sonatype og/eller maven centrale repositories ved hjælp af GitLab. I denne artikel vil jeg tale om opsætning af gitlab-runner, gitlab-ci og maven-plugin for at løse dette problem.
Forudsætninger:
Sikker opbevaring af mvn og GPG nøgler.
Sikker udførelse af offentlige CI-opgaver.
Upload af artefakter (frigivelse/snapshot) til offentlige arkiver.
Automatisk kontrol af udgivelsesversioner til offentliggørelse i maven central.
En generel løsning til upload af artefakter til et lager for flere projekter.
En detaljeret beskrivelse af mekanismen til udgivelse af artefakter til Maven Central via Sonatype OSS Repository Hosting Service er allerede beskrevet i denne artikel bruger googolplex, så jeg vil henvise til denne artikel de rigtige steder.
Forhåndstilmelding kl Sonatype JIRA og start en billet for at åbne lageret (læs afsnittet for flere detaljer Opret en Sonatype JIRA-billet). Efter åbning af lageret vil JIRA login/adgangskodeparret (herefter kaldet Sonatype-kontoen) blive brugt til at uploade artefakter til Sonatype-forbindelsen.
Hvis du bruger Linux-konsollen til at generere en GPG-nøgle (gnupg/gnupg2), skal du installere RNG-værktøjer at generere entropi. Ellers kan nøglegenerering tage meget lang tid.
Først og fremmest skal du oprette og konfigurere et projekt, hvor pipelinen vil blive gemt til udrulning af artefakter. Jeg kaldte mit projekt enkelt og ukompliceret - indsætte
Efter at have oprettet depotet, skal du begrænse adgangen for at ændre depotet.
Gå til projektet -> Indstillinger -> Depot -> Beskyttede grene. Vi sletter alle regler og tilføjer en enkelt regel med Wildcard * med ret til at push og flette kun for brugere med rollen Maintainers. Denne regel vil fungere for alle brugere af både dette projekt og gruppen, som dette projekt tilhører.
Hvis der er flere vedligeholdere, så vil den bedste løsning være at begrænse adgangen til projektet i princippet.
Gå til projektet -> Indstillinger -> Generelt -> Synlighed, projektfunktioner, tilladelser og indstil Projektsynlighed til Privat.
Jeg har et projekt i offentlig adgang, da jeg bruger min egen GitLab Runner og kun jeg har adgang til at ændre depotet. Nå, faktisk er det ikke i min interesse at vise private oplysninger i offentlige pipeline logs.
Skærpelse af reglerne for ændring af depotet
Gå til projektet -> Indstillinger -> Repository -> Push Rules og indstil flagene Committer-begrænsning, Tjek om forfatteren er en GitLab-bruger. Jeg anbefaler også indstilling forpligte sig til at underskrive, og indstil flaget Reject unsigned commits.
Dernæst skal du konfigurere en trigger for at køre opgaver
Gå til projekt -> Indstillinger -> CI / CD -> Pipeline-udløsere og opret et nyt trigger-token
Dette token kan straks føjes til den generelle konfiguration af variabler for en gruppe af projekter.
Gå til gruppen -> Indstillinger -> CI / CD -> Variabler og tilføj en variabel DEPLOY_TOKEN med trigger-token i værdien.
Dette afsnit beskriver konfigurationen for at køre opgaver ved implementering ved hjælp af den oprindelige (specifikke) og offentlige (delte) runner.
Specifik løber
Jeg bruger mine egne løbere, fordi det først og fremmest er praktisk, hurtigt, billigt.
For runner anbefaler jeg Linux VDS med 1 CPU, 2 GB RAM, 20 GB HDD. Udstedelsespris ~ 3000 ₽ om året.
Min løber
Til løberen tog jeg VDS 4 CPU, 4 GB RAM, 50 GB SSD. Det kostede ~11000₽ og har aldrig fortrudt det.
Jeg har i alt 7 maskiner. 5 på aruba og 2 på ihor.
Så vi har en løber. Nu sætter vi det op.
Vi går til maskinen via SSH og installerer java, git, maven, gnupg2.
Opret en mappe til maven-cachen og tildel grupperettigheder runner
Du kan springe dette trin over, hvis du ikke planlægger at køre flere løbere på samme maskine.
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!
Tjek at løberen er tilmeldt. Gå til gitlab.com -> deploy-project -> Indstillinger -> CI/CD -> Løbere -> Specifikke løbere -> Løbere aktiveret for dette projekt
Skærm
Tilføjelse adskille service /etc/systemd/system/gitlab-deployer.service
Vi genererer en nøgle ved at besvare spørgsmål. Jeg brugte mit eget navn og e-mail.
Sørg for at angive adgangskoden til nøglen. Artefakter vil blive signeret med denne nøgle.
gpg --gen-key
Kontrol
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
Uploader vores offentlige nøgle til nøgleserveren
gpg --keyserver keys.gnupg.net --send-key 00000000
gpg: sending key 00000000 to hkp server keys.gnupg.net
Opret en maven-mappe Repository og link til cachen (tag ikke fejl)
Dette trin kan springes over, hvis du ikke planlægger at køre flere løbere på samme maskine.
Tilføj filen .gitlab-ci.yml til roden af implementeringsprojektet
Scriptet præsenterer to gensidigt udelukkende implementeringsopgaver. Henholdsvis specifik løber eller delt løber.
.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>
Hvis du har et modul, der ikke indeholder java (f.eks. kun ressourcer)
Eller du ønsker ikke at generere javadoc i princippet, så for at hjælpe maven-jar-plugin
Hvis du har et multi-modul projekt, og du ikke behøver at uploade et specifikt modul til repository, så skal du tilføje til pom.xml af dette modul nexus-staging-maven-plugin med flag skipNexusStagingDeployMojo
<repositories>
<repository>
<id>SonatypeNexus</id>
<url>https://oss.sonatype.org/content/groups/staging/</url>
<!-- Не надо указывать флаги snapshot/release для репозитория -->
</repository>
</repositories>
Flere plusser
En meget rig liste over mål for at arbejde med nexus-lageret (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
Automatisk udgivelsestjek for downloadbarhed i maven central
Når tagget er indstillet, udløses den tilsvarende opgave i implementeringsprojektet automatisk for at uploade udgivelsesversionen til nexus (eksempel).
Det bedste er, at close release automatisk udløses i 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] ------------------------------------------------------------------------
Og hvis noget gik galt, så mislykkes opgaven
[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] ------------------------------------------------------------------------
Som et resultat står vi kun tilbage med ét valg. Eller slet denne version eller udgiv.
Efter udgivelsen, efter nogen tid, vil artefakterne være inde
udenfor emne
Det var en åbenbaring for mig, at Maven indekserer andre offentlige arkiver.
Jeg var nødt til at uploade robots.txt, fordi det indekserede mit gamle depot.
Et separat implementeringsprojekt, hvor du kan implementere adskillige CI-opgaver til upload af artefakter til offentlige arkiver til forskellige udviklingssprog.
Implementeringsprojektet er isoleret fra ekstern interferens og kan kun ændres af brugere med rollerne Ejer og Vedligeholder.
En separat Specifik Runner med en "hot" cache til kun at køre implementeringsopgaver.
Offentliggørelse af snapshot-/frigivelsesversioner i et offentligt lager.
Automatisk kontrol af udgivelsesversionen for klarhed til offentliggørelse i maven central.
Beskyttelse mod automatisk udgivelse af "rå" versioner i maven central.
Byg og udgiv snapshotversioner "ved klik".
Enkelt lager til at få snapshot/udgivelsesversioner.
Generel pipeline til opbygning / test / publicering af et java-projekt.
Opsætning af GitLab CI er ikke et så kompliceret emne, som det ser ud til ved første øjekast. Det er nok at sætte CI op på nøglefærdig basis et par gange, og nu er du langt fra en amatør i denne sag. Desuden er GitLab-dokumentation meget overflødig. Vær ikke bange for at tage det første skridt. Vejen vises under trinene på den, der går (jeg kan ikke huske, hvem der sagde det :)
Jeg vil være glad for feedback.
I den næste artikel vil jeg vise dig, hvordan du konfigurerer GitLab CI til at køre integrationstestopgaver konkurrencedygtigt (kører testtjenester med docker-compose), hvis du kun har én shell-løber.