Questo articolo è destinato agli sviluppatori Java che hanno bisogno di pubblicare rapidamente i propri prodotti nei repository di Sonatype e/o Maven Central utilizzando GitLab. In questo articolo parlerò della configurazione di gitlab-runner, gitlab-ci e del maven-plugin per affrontare questo compito.
Prerequisiti:
- Archiviazione sicura delle chiavi mvn e GPG.
- Esecuzione sicura di attività CI pubbliche.
- Caricamento di artefatti (release/snapshot) nei repository pubblici.
- Verifica automatica delle versioni release per la pubblicazione in Maven Central.
- Soluzione generale per il caricamento di artefatti in un repository per più progetti.
- Semplicità e facilità d'uso.
Contenuto
Informazioni generali
- Una descrizione dettagliata del meccanismo di pubblicazione degli artefatti in Maven Central tramite il Sonatype OSS Repository Hosting Service è già stata descritta in da parte dell'utente , quindi farò riferimento a questo articolo nei luoghi necessari.
- Registriamoci preliminarmente in e apriamo un ticket per l'apertura del repository (per dettagli, vedere la sezione ). Una volta aperto il repository, la coppia login/password di JIRA (poi l'account Sonatype) sarà utilizzata per caricare gli artefatti in Sonatype nexus.
- Il processo di generazione della chiave GPG è descritto in modo piuttosto scarno. Per dettagli, vedere la sezione
- Se usi la console Linux per generare la chiave GPG (gnupg/gnupg2), è necessario installare per generare entropia. Altrimenti, la generazione della chiave potrebbe richiedere molto tempo.
- Servizi di archiviazione chiavi GPG pubbliche
Impostazione del progetto di deploy in GitLab
- Innanzitutto, è necessario creare e configurare un progetto in cui sarà archiviato il pipeline per il deploy degli artefatti. Ho chiamato il mio progetto in modo semplice e diretto —
- Dopo aver creato il repository, è necessario limitare l'accesso alle modifiche del repository.
Passiamo al progetto -> Impostazioni -> Repository -> Rami protetti. Rimuoviamo tutte le regole e aggiungiamo una sola regola con Wildcard * con il diritto di push e merge solo per gli utenti con il ruolo di Maintainers. Questa regola funzionerà per tutti gli utenti sia di questo progetto che del gruppo a cui appartiene.
- Se ci sono più maintainers, la soluzione migliore sarà limitare l'accesso al progetto in generale.
Passiamo al progetto -> Impostazioni -> Generale -> Visibilità, caratteristiche del progetto, permessi e impostiamo la visibilità del progetto su Privato.
Ho un progetto con accesso pubblico, poiché uso il mio GitLab Runner e l'accesso per modificare il repository è solo per me. Inoltre, non è nel mio interesse rivelare informazioni private nei log pubblici dei pipeline. - Rafforzamento delle regole per la modifica del repository
Passiamo al progetto -> Impostazioni -> Repository -> Regole di Push e attiviamo i flag del Restrizione del Committer, Controlla se l'autore è un utente GitLab. Consiglio anche di configurare , e attivare il flag Rifiuta commit non firmati. - Successivamente, è necessario configurare un trigger per avviare i task
Passiamo al progetto -> Impostazioni -> CI / CD -> Trigger del pipeline e creiamo un nuovo trigger-token
Questo token può essere aggiunto direttamente alla configurazione delle variabili per il gruppo di progetti.
Andiamo nel gruppo -> Settings -> CI / CD -> Variables e aggiungiamo la variabileDEPLOY_TOKENcon trigger-token nel valore.
GitLab Runner
In questa sezione è descritta la configurazione per avviare compiti di deploy utilizzando runner privati (Specific) e pubblici (Shared).
Specific Runner
Uso runner privati, poiché è comodo, veloce ed economico.
Per il runner consiglio una VDS Linux con 1 CPU, 2 GB di RAM, 20 GB di HDD. Il costo è di circa 3000₽ all'anno.
Il mio runner
Per il runner ho scelto una VDS con 4 CPU, 4 GB di RAM, 50 GB di SSD. Mi è costata circa 11000₽ e non me ne sono mai pentito.
In totale ho 7 macchine. 5 su Aruba e 2 su Ihor.
Quindi, abbiamo un runner. Ora lo configureremo.
Accediamo alla macchina via SSH e installiamo Java, git, maven, gnupg2.
Installiamo gitlab runner
- Creiamo un nuovo gruppo
runnersudo groupadd runner - Creiamo una directory per la cache di maven e assegniamo i permessi al gruppo
runner
Questo passaggio può essere saltato se non prevedi di eseguire più runner sulla stessa macchina.mkdir -p /usr/cache/.m2/repository chown -R :runner /usr/cache chmod -R 770 /usr/cache - Creiamo un utente
gitlab-deployere aggiungiamo al grupporunneruseradd -m -d /home/gitlab-deployer gitlab-deployer usermod -a -G runner gitlab-deployer - Aggiungiamo al file
/etc/ssh/sshd_configla riga successivaAllowUsers root@* gitlab-deployer@127.0.0.1 - Riavviando
sshdsystemctl restart sshd - Impostiamo la password per l'utente
gitlab-deployer(può essere semplice, poiché ci sono limitazioni per localhost)passwd gitlab-deployer - Installiamo GitLab Runner (Linux x86-64)
sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 sudo chmod +x /usr/local/bin/gitlab-runner ln -s /usr/local/bin/gitlab-runner /etc/alternatives/gitlab-runner ln -s /etc/alternatives/gitlab-runner /usr/bin/gitlab-runner - Andiamo su gitlab.com -> deploy-project -> Impostazioni -> CI/CD -> Runners -> Runners specifici e copiamo il registration token
Screenshot
- Registriamo il runner
gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml
Processo
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!- Controlliamo che il runner sia registrato. Andiamo su gitlab.com -> deploy-project -> Impostazioni -> CI/CD -> Runners -> Runners specifici -> Runners attivati per questo progetto
Screenshot
- Aggiungiamo separato servizio
/etc/systemd/system/gitlab-deployer.service[Unit] Description=GitLab Deploy Runner After=syslog.target network.target ConditionFileIsExecutable=/usr/local/bin/gitlab-runner [Service] StartLimitInterval=5 StartLimitBurst=10 ExecStart=/usr/local/bin/gitlab-runner "run" "--working-directory" "/home/gitlab-deployer" "--config" "/etc/gitlab-runner/gitlab-deployer-config.toml" "--service" "gitlab-deployer" "--syslog" "--user" "gitlab-deployer" Restart=always RestartSec=120 [Install] WantedBy=multi-user.target - Avviamo il servizio.
systemctl enable gitlab-deployer.service systemctl start gitlab-deployer.service systemctl status gitlab-deployer.service - Controlliamo che il runner sia avviato.
Esempio
Generazione delle chiavi GPG
- Dalla stessa macchina, accediamo via ssh con l'utente
gitlab-deployer(questo è importante per generare la chiave GPG)ssh gitlab-deployer@127.0.0.1 - Generiamo la chiave rispondendo alle domande. Ho usato il mio nome e la mia email.
Assicuriamoci di specificare una password per la chiave. Questa chiave sarà utilizzata per firmare gli artefatti.gpg --gen-key - Controlliamo
gpg --list-keys -a /home/gitlab-deployer/.gnupg/pubring.gpg ---------------------------------------- pub 4096R/00000000 2019-04-19 uid Petruha Petrov <pp@example.com> sub 4096R/11111111 2019-04-19 - Carichiamo la nostra chiave pubblica sul server chiavi
gpg --keyserver keys.gnupg.net --send-key 00000000 gpg: invio della chiave 00000000 al server hkp keys.gnupg.net
Configurazione di Maven
- Accediamo con l'utente
gitlab-deployersu gitlab-deployer - Creiamo la directory maven repository e colleghiamo con la cache (non sbagliatevi)
Questo passaggio può essere saltato se non prevedete di avviare più runner sulla stessa macchina.mkdir -p ~/\.m2\/repository ln -s /usr/cache/.m2/repository /home/gitlab-deployer/.m2/repository - Creiamo la chiave master
mvn --encrypt-master-password password {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=} - Creiamo il file ~/\.m2\/settings-security.xml
{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=} - Cifriamo la password dell'account Sonatype
mvn --encrypt-password SONATYPE_PASSWORD {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J} - Creiamo il file ~/\.m2\/settings.xml
env true GPG_SECRET_KEY_PASSPHRASE sonatype SONATYPE_USERNAME {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
dove,
GPG_SECRET_KEY_PASSPHRASE — password della chiave GPG
SONATYPE_USERNAME — login dell'account sonatype
A questo punto, la configurazione del runner è completata, possiamo passare alla sezione
Shared Runner
Generazione delle chiavi GPG
- Prima di tutto è necessario creare una chiave GPG. Per fare ciò, installiamo gnupg.
yum install -y gnupg - Generiamo una chiave rispondendo a delle domande. Ho utilizzato il mio nome e la mia email. Assicurati di specificare una password per la chiave.
gpg --gen-key - Visualizziamo le informazioni sulla chiave
gpg --list-keys -a pub rsa3072 2019-04-24 [SC] [scadenza: 2021-04-23] 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 uid [ultimate] tttemp sub rsa3072 2019-04-24 [E] [scadenza: nessuna] - Carichiamo la nostra chiave pubblica sul server chiavi
gpg --keyserver keys.gnupg.net --send-key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 gpg: invio della chiave 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 al server hkp keys.gnupg.net - Acquisiamo la chiave privata
gpg --export-secret-keys --armor 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 -----BEGIN PGP PRIVATE KEY BLOCK----- lQWGBFzAqp8BDADN41CPwJ/gQwiKEbyA902DKw/WSB1AvZQvV/ZFV77xGeG4K7k5 ... =2Wd2 -----END PGP PRIVATE KEY BLOCK----- - Andiamo su impostazioni del progetto -> Settings -> CI / CD -> Variables e salviamo la chiave privata nella variabile
GPG_SECRET_KEY
Configurazione di Maven
- Creiamo la chiave master
mvn --encrypt-master-password password {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=} - Andiamo su impostazioni del progetto -> Settings -> CI / CD -> Variables e salviamo nella variabile
SETTINGS_SECURITY_XMLle seguenti righe:{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=} - Cifriamo la password dell'account Sonatype
mvn --encrypt-password SONATYPE_PASSWORD {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J} - Andiamo su impostazioni del progetto -> Settings -> CI / CD -> Variables e salviamo nella variabile
SETTINGS_XMLle seguenti righe:env true GPG_SECRET_KEY_PASSPHRASE sonatype sonatype_username {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
dove,
GPG_SECRET_KEY_PASSPHRASE — password della chiave GPG
SONATYPE_USERNAME — login dell'account sonatype
Deploy dell'immagine Docker
- Creiamo un Dockerfile abbastanza semplice per eseguire attività di deploy con la versione corretta di Java. Di seguito è riportato un esempio 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/ - Costruiamo un contenitore per il vostro progetto
docker build -t registry.gitlab.com/group/deploy . - Autentichiamoci e carichiamo il contenitore nel registry.
docker login -u USER -p PASSWORD registry.gitlab.com docker push registry.gitlab.com/group/deploy
GitLab CI
Deploy del progetto
Aggiungiamo un file .gitlab-ci.yml nella radice del progetto di deploy
Lo script presenta due attività di deploy che si escludono a vicenda. Specific Runner o Shared Runner rispettivamente.
.gitlab-ci.yml
fasi:
- distribuzione
Runner Specifico:
extends: .java_deploy_template
# Il compito sarà eseguito sul tuo runner shell
tags:
- distribuzione
Runner Condiviso:
extends: .java_deploy_template
# Il compito sarà eseguito su un docker runner pubblico
tags:
- docker
# Immagine dalla sezione GitLab Runner -> Runner Condivisi -> Docker
image: registry.gitlab.com/group/deploy-project:latest
before_script:
# Importiamo la chiave GPG
- printf "${GPG_SECRET_KEY}" | gpg --batch --import
# Salviamo la configurazione di maven
- printf "${SETTINGS_SECURITY_XML}" > ~/.m2/settings-security.xml
- printf "${SETTINGS_XML}" > ~/.m2/settings.xml
.java_deploy_template:
stage: distribuzione
# Il compito sarà attivato tramite trigger, se viene passata la variabile DEPLOY con valore java
only:
variables:
- $DEPLOY == "java"
variables:
# disabilitiamo il clonaggio del progetto corrente
GIT_STRATEGY: none
script:
# Permettiamo di memorizzare la password in chiaro
- git config --global credential.helper store
# Salviamo le credenziali temporanee dell'utente gitlab-ci-token
# Il token funziona per tutti i progetti pubblici su gitlab.com e per i progetti di gruppo
- echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
# Pulisci completamente la directory corrente
- rm -rf .* *
# Cloniamo il progetto che andremo a distribuire in Sonatype Nexus
- git clone ${DEPLOY_CI_REPOSITORY_URL} .
# Cambiamo al commit necessario
- git checkout ${DEPLOY_CI_COMMIT_SHA} -f
# Se anche uno dei pom.xml contiene il parametro autoReleaseAfterClose, annulliamo la build.
# Altrimenti c'è il rischio di caricare artefatti non stabili in maven central
- >
for pom in $(find . -name pom.xml); do
if [[ $(grep -q autoReleaseAfterClose "$pom" && echo $?) == 0 ]]; then
echo "File $pom contiene impostazione vietata: <autoReleaseAfterClose>";
exit 1;
fi;
done
# Se il parametro DEPLOY_CI_COMMIT_TAG è vuoto, impostiamo forzatamente la versione 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
# Eseguiamo il compito di build e distribuzione degli artefatti
- mvn clean deploy -DskipTests=trueProgetto Java
Nei progetti Java destinati a essere caricati in repository pubblici è necessario aggiungere 2 passaggi per il caricamento delle versioni Release e Snapshot.
.gitlab-ci.yml
stages:
- build
- test
- verify
- deploy
Release:
extends: .trigger_deploy
# Esegui il task solo per il tag.
only:
- tags
Snapshot:
extends: .trigger_deploy
# Avviare manualmente il task per pubblicare la versione SNAPSHOT
when: manual
# Non eseguire il task se è stato impostato un tag.
except:
- tags
.trigger_deploy:
stage: deploy
variables:
# Disabilita il cloning del progetto corrente
GIT_STRATEGY: none
# Link al trigger del task di deploy
URL: "https://gitlab.com/api/v4/projects//trigger/pipeline"
# Variabili del task di deploy
POST_DATA: "
token=${DEPLOY_TOKEN}&
ref=master&
variables[DEPLOY]=${DEPLOY}&
variables[DEPLOY_CI_REPOSITORY_URL]=${CI_REPOSITORY_URL}&
variables[DEPLOY_CI_PROJECT_NAME]=${CI_PROJECT_NAME}&
variables[DEPLOY_CI_COMMIT_SHA]=${CI_COMMIT_SHA}&
variables[DEPLOY_CI_COMMIT_TAG]=${CI_COMMIT_TAG}
"
script:
# Non uso cURL, poiché con i flag --fail --show-error
# non mostra il corpo della risposta se il codice HTTP è 400 o superiore
- wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}In questa soluzione sono andato un po' oltre e ho deciso di usare un singolo template CI per i progetti java.
Maggiore chiarezza
Ho creato un progetto separato in cui ho collocato il template CI per i progetti java .
common.yml
fasi:
- costruzione
- test
- verifica
- distribuzione
variabili:
SONAR_ARGS: "
-Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA}
-Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME}
"
.build_java_project:
fase: costruzione
tag:
- touchbit-shell
variabili:
SKIP_TEST: "false"
script:
- mvn clean
- mvn package -DskipTests=${SKIP_TEST}
artefatti:
when: always
expire_in: 30 giorno
percorsi:
- "*/target/reports"
.build_sphinx_doc:
fase: costruzione
tag:
- touchbit-shell
variabili:
DOCKERFILE: .indirect/docs/Dockerfile
script:
- docker build --no-cache -t ${CI_PROJECT_NAME}/doc -f ${DOCKERFILE} .
.junit_module_test_run:
fase: test
tag:
- touchbit-shell
variabili:
MODULE: ""
script:
- cd ${MODULE}
- mvn test
artefatti:
when: always
expire_in: 30 giorno
percorsi:
- "*/target/reports"
.junit_test_run:
fase: test
tag:
- touchbit-shell
script:
- mvn test
artefatti:
when: always
expire_in: 30 giorno
percorsi:
- "*/target/reports"
.sonar_review:
fase: verifica
tag:
- touchbit-shell
dipendenze: []
script:
- >
if [ "$CI_BUILD_REF_NAME" == "master" ]; then
mvn compile sonar:sonar -Dsonar.login=$SONAR_LOGIN $SONAR_ARGS
else
mvn compile sonar:sonar -Dsonar.login=$SONAR_LOGIN $SONAR_ARGS -Dsonar.analysis.mode=preview
fi
.trigger_deploy:
fase: distribuzione
tag:
- touchbit-shell
variabili:
URL: "https://gitlab.com/api/v4/projects/10345765/trigger/pipeline"
POST_DATA: "
token=${DEPLOY_TOKEN}&
ref=master&
variables[DEPLOY]=${DEPLOY}&
variables[DEPLOY_CI_REPOSITORY_URL]=${CI_REPOSITORY_URL}&
variables[DEPLOY_CI_PROJECT_NAME]=${CI_PROJECT_NAME}&
variables[DEPLOY_CI_COMMIT_SHA]=${CI_COMMIT_SHA}&
variables[DEPLOY_CI_COMMIT_TAG]=${CI_COMMIT_TAG}
"
script:
- wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}
.trigger_release_deploy:
estende: .trigger_deploy
solo:
- tags
.trigger_snapshot_deploy:
estende: .trigger_deploy
quando: manuale
eccetto:
- tags
Di conseguenza, nei progetti java stessi, il file .gitlab-ci.yml risulta piuttosto compatto e conciso.
.gitlab-ci.yml
include: https://gitlab.com/TouchBIT/gitlab-ci/raw/master/common.yml
Shields4J:
extends: .build_java_project
Sphinx doc:
extends: .build_sphinx_doc
variables:
DOCKERFILE: .docs/Dockerfile
Sonar review:
extends: .sonar_review
dependencies:
- Shields4J
Release:
extends: .trigger_release_deploy
Snapshot:
extends: .trigger_snapshot_deployConfigurazione pom.xml
Questo argomento è descritto in modo molto dettagliato. in , quindi descriverò alcune sfumature relative all'uso dei plugin. Inoltre, spiegherò quanto sia semplice e naturale utilizzare nexus-staging-maven-plugin, se non si desidera o non si può utilizzare org.sonatype.oss:oss-parent come genitore per il proprio progetto.
maven-install-plugin
Installa i moduli nel repository locale.
Molto utile per un controllo locale delle soluzioni in altri progetti, oltre che per la somma di controllo.
org.apache.maven.plugins
maven-install-plugin
install-project
install
target/${project.artifactId}-${project.version}.jar
```target/${project.artifactId}-${project.version}-sources.jar
dependency-reduced-pom.xml
true
truemaven-javadoc-plugin
Generazione della javadoc per il progetto.
org.apache.maven.plugins
maven-javadoc-plugin
jar
prepare-package
true
true
falseSe hai un modulo che non contiene java (ad esempio solo risorse)
Oppure non desideri generare javadoc, ecco come procedere maven-jar-plugin
org.apache.maven.plugins
maven-jar-plugin
empty-javadoc-jar
generate-resources
jar
javadoc
${basedir}/javadocmaven-gpg-plugin
org.apache.maven.plugins
maven-gpg-plugin
sign-artifacts
deploy
signnexus-staging-maven-plugin
Configurazione:
org.sonatype.plugins
nexus-staging-maven-plugin
org.sonatype.plugins
nexus-staging-maven-plugin
true
sonatype
https://oss.sonatype.org/
true
org.apache.maven.plugins
maven-deploy-plugin
true
sonatype
Repository Nexus Snapshot
https://oss.sonatype.org/content/repositories/snapshots/
sonatype
Repository Nexus Release
https://oss.sonatype.org/service/local/staging/deploy/maven2/Se hai un progetto multi-modulo e non è necessario caricare un modulo specifico nel repository, devi aggiungere nel pom.xml di questo modulo nexus-staging-maven-plugin con il flag skipNexusStagingDeployMojo
org.sonatype.plugins
nexus-staging-maven-plugin
trueDopo il caricamento, la versione snapshot/release è disponibile in
SonatypeNexus
https://oss.sonatype.org/content/groups/staging/
Altri vantaggi
- Un elenco molto ricco di obiettivi per lavorare con il repository nexus (
mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin). - Controllo automatico delle versioni per il caricamento nel maven central
Risultato
Pubblicazione della versione SNAPSHOT
Durante la build del progetto, è possibile avviare manualmente il compito di caricamento della versione SNAPSHOT nel nexus
Quando viene avviato questo compito, si attiva il compito corrispondente nel progetto deploy ().
Log abbreviato
Esecuzione con gitlab-runner 11.10.0 (3001a600)
su Deploy runner JSKWyxUw
Utilizzando l'esecutore Shell...
In esecuzione su ih1174328.vds.myihor.ru...
Saltando la configurazione del repository Git
Saltando il checkout di Git
Saltando la configurazione dei sottogruppi di Git
$ rm -rf .* *
$ git config --global credential.helper store
$ echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/ .git-credentials
$ git clone ${DEPLOY_CI_REPOSITORY_URL} .
Clonazione in 'shields4j'...
$ git checkout ${DEPLOY_CI_COMMIT_SHA}
Nota: checkout di '850f86aa317194395c5387790da1350e437125a7'.
Sei in uno stato 'detached HEAD'. Puoi esplorare, apportare modifiche sperimentali
e confermarle, e puoi scartare eventuali commit creati in questo
stato senza influenzare alcun ramo eseguendo un altro checkout.
Se vuoi creare un nuovo ramo per mantenere i commit creati, puoi
farlo (ora o più tardi) utilizzando -b con il comando checkout di nuovo. Esempio:
git checkout -b new_branch_name
HEAD è ora a 850f86a... salta il test di distribuzione core
$ for pom in $(find . -name pom.xml); do # comando multi-linea accorpato
$ if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then # comando multi-linea accorpato
[INFO] Scansione dei progetti...
[INFO] Ispezionando la build con un totale di 4 moduli...
[INFO] Installazione delle funzionalità di Nexus Staging:
[INFO] ... un totale di 4 esecuzioni di maven-deploy-plugin sostituite con nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Ordine di build del reattore:
[INFO]
[INFO] Shields4J [pom]
[INFO] test-core [jar]
[INFO] Shields4J client [jar]
[INFO] TestNG listener [jar]
[INFO]
[INFO] -----------------------------
[INFO] Costruzione di Shields4J 1.0.0 [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- versions-maven-plugin:2.5:set (default-cli) @ shields4j-parent ---
[INFO] Ricerca della radice locale dell'aggregatore...
[INFO] Radice di aggregazione locale: /home/gitlab-deployer/JSKWyxUw/0/TouchBIT/deploy/shields4j
[INFO] Elaborazione della modifica di org.touchbit.shields4j:shields4j-parent:1.0.0 -> 1.0.0-SNAPSHOT
[INFO] Elaborazione di org.touchbit.shields4j:shields4j-parent
[INFO] Aggiornamento del progetto org.touchbit.shields4j:shields4j-parent
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO]
[INFO] Elaborazione di org.touchbit.shields4j:client
[INFO] Aggiornamento del genitore org.touchbit.shields4j:shields4j-parent
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO] Aggiornamento della dipendenza org.touchbit.shields4j:test-core
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO]
[INFO] Elaborazione di org.touchbit.shields4j:test-core
[INFO] Aggiornamento del genitore org.touchbit.shields4j:shields4j-parent
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO]
[INFO] Elaborazione di org.touchbit.shields4j:testng
[INFO] Aggiornamento del genitore org.touchbit.shields4j:shields4j-parent
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO] Aggiornamento della dipendenza org.touchbit.shields4j:client
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO] Aggiornamento della dipendenza org.touchbit.shields4j:test-core
[INFO] dalla versione 1.0.0 alla 1.0.0-SNAPSHOT
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Riepilogo del reattore:
[INFO]
[INFO] Shields4J 1.0.0 .................................... SUCCESS [ 0.992 s]
[INFO] test-core .......................................... SKIPPED
[INFO] Shields4J client ................................... SKIPPED
[INFO] TestNG listener 1.0.0 .............................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] COSTRUZIONE RIUSCITA
[INFO] ------------------------------------------------------------------------
[INFO] Tempo totale: 2.483 s
[INFO] Terminato alle: 2019-04-21T02:40:42+03:00
[INFO] ------------------------------------------------------------------------
$ mvn clean deploy -DskipTests=${SKIP_TESTS}
[INFO] Scansione dei progetti...
[INFO] Ispezionando la build con un totale di 4 moduli...
[INFO] Installazione delle funzionalità di Nexus Staging:
[INFO] ... un totale di 4 esecuzioni di maven-deploy-plugin sostituite con nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Ordine di build del reattore:
[INFO]
[INFO] Shields4J [pom]
[INFO] test-core [jar]
[INFO] Shields4J client [jar]
[INFO] TestNG listener [jar]
[INFO]
[INFO] -----------------------------
[INFO] Costruzione di Shields4J 1.0.0-SNAPSHOT [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
...
DELETTO
...
[INFO] * Distribuzione in blocco degli artefatti snapshot raccolti localmente completata.
[INFO] Distribuzione remota completata con successo.
[INFO] ------------------------------------------------------------------------
[INFO] Riepilogo del reattore:
[INFO]
[INFO] Shields4J 1.0.0-SNAPSHOT ........................... SUCCESS [ 2.375 s]
[INFO] test-core .......................................... SUCCESS [ 3.929 s]
[INFO] Shields4J client ................................... SUCCESS [ 3.815 s]
[INFO] TestNG listener 1.0.0-SNAPSHOT ..................... SUCCESS [ 36.134 s]
[INFO] ------------------------------------------------------------------------
[INFO] COSTRUZIONE RIUSCITA
[INFO] ------------------------------------------------------------------------
[INFO] Tempo totale: 47.629 s
[INFO] Terminato alle: 2019-04-21T02:41:32+03:00
[INFO] ------------------------------------------------------------------------Di conseguenza, è stata caricata una versione nel nexus .
Tutte le versioni snapshot possono essere eliminate dal repository sul sito sotto il tuo account.
Pubblicazione della versione release
Quando si imposta il tag, viene automaticamente attivata la relativa attività nel progetto deploy per caricare la versione di rilascio nel nexus ().
La cosa più piacevole è che si attiva automaticamente il close release nel nexus.
[INFO] Esecuzione del caricamento remoto...
[INFO]
[INFO] * Caricamento remoto nel profilo di staging ID "9043b43f77dcc9"
[INFO] * Repository di staging creato con ID "orgtouchbit-1037".
[INFO] * Repository di staging su https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1037
[INFO] * Caricamento degli artifact locali nello staging profile org.touchbit
[INFO] * Caricamento degli artifact locali nello staging completato.
[INFO] * Chiusura del repository di staging con ID "orgtouchbit-1037".
Attesa del completamento dell'operazione...
.........
[INFO] 1 repository remoto caricato in staging, completato con successo.
[INFO] ------------------------------------------------------------------------
[INFO] Riepilogo del reattore:
[INFO]
[INFO] Shields4J 1.0.0 .................................... SUCCESS [ 9.603 s]
[INFO] test-core .......................................... SUCCESS [ 3.419 s]
[INFO] Client Shields4J ................................... SUCCESS [ 9.793 s]
[INFO] Listener TestNG 1.0.0 .............................. SUCCESS [01:23 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Tempo totale: 01:47 min
[INFO] Finito il: 2019-04-21T04:05:46+03:00
[INFO] ------------------------------------------------------------------------E se qualcosa va storto, il compito sicuramente fallirà
[INFO] Esecuzione del staging remoto...
[INFO]
[INFO] * Staging remoto nel profilo di staging ID "9043b43f77dcc9"
[INFO] * Repository di staging creato con ID "orgtouchbit-1038".
[INFO] * Repository di staging presso https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1038
[INFO] * Caricamento degli artifact in staging locale nel profilo org.touchbit
[INFO] * Caricamento degli artifact in staging locale terminato.
[INFO] * Chiusura del repository di staging con ID "orgtouchbit-1038".
Attendere il completamento dell'operazione...
.......
[ERROR] Fallimento della regola durante il tentativo di chiusura del repository di staging con ID "orgtouchbit-1039".
[ERROR]
[ERROR] Rapporto di fallimento delle regole di staging di Nexus
[ERROR] ==================================
[ERROR]
[ERROR] Fallimenti del repository "orgtouchbit-1039"
[ERROR] Fallimenti della regola "signature-staging"
[ERROR] * Nessuna chiave pubblica: La chiave con ID: (1f42b618d1cbe1b5) non è stata trovata su http://keys.gnupg.net:11371/. Carica la tua chiave pubblica e riprova l'operazione.
...
[ERROR] Pulizia della directory locale di staging dopo un fallimento della regola durante la chiusura dei repository di staging: [orgtouchbit-1039]
[ERROR] * Eliminazione del contesto 9043b43f77dcc9.properties
[ERROR] Pulizia dei repository di staging remoto dopo un fallimento della regola durante la chiusura dei repository di staging: [orgtouchbit-1039]
[ERROR] * Eliminazione del repository di staging fallito con ID "orgtouchbit-1039" (Fallimento della regola durante la chiusura dei repository di staging: [orgtouchbit-1039]).
[ERROR] Staging remoto terminato con un errore: Fallimento delle regole di staging!
[INFO] ------------------------------------------------------------------------
[INFO] Riepilogo del reattore:
[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] FALLIMENTO DEL BUILD
[INFO] ------------------------------------------------------------------------Rimane solo una scelta: eliminare questa versione o pubblicarla.
Dopo il rilascio, dopo un po' gli artefatti si troveranno in
off-topic
È stata una scoperta per me che Maven indicizza altri repository pubblici.
Ho dovuto includere robots.txt, poiché ha indicizzato il mio vecchio repository.
Conclusione
Cosa abbiamo
- Un progetto di deploy separato in cui possono essere implementate diverse attività CI per caricare artefatti in repository pubblici per vari linguaggi di programmazione.
- Il progetto di deploy è isolato da interferenze esterne e può essere modificato solo da utenti con il ruolo di Owner e Maintainer.
- Un Specific Runner separato con una cache 'calda' per eseguire solo le attività di deploy.
- Pubblicazione di versioni snapshot/release in un repository pubblico.
- Controllo automatico della versione release per la prontezza alla pubblicazione su Maven Central.
- Protezione contro la pubblicazione automatica di versioni 'grezze' su Maven Central.
- Assemblaggio e pubblicazione delle versioni snapshot 'con un clic'.
- Un repository unico per ottenere versioni snapshot/release.
- Pipeline comune per build/test/pubblicazione di un progetto Java.
La configurazione di GitLab CI non è così complicata come potrebbe sembrare a prima vista. Basta configurare CI "chiavi in mano" un paio di volte e voilà, non sei più un principiante in questo campo. Inoltre, la documentazione di GitLab è piuttosto esaustiva. Non avere paura di fare il primo passo. La strada si forma sotto i passi di chi procede (non ricordo chi l'ha detto 🙂 ).
Sarei felice di ricevere un feedback.
Nel prossimo articolo parlerò di come configurare GitLab CI per l'esecuzione concorrente di task con test di integrazione (eseguendo i servizi testati tramite docker-compose), se hai solo un runner shell.
Fonte: habr.com
