Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

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 questo articolo da parte dell'utente Googolplex, quindi farò riferimento a questo articolo nei luoghi necessari.
  • Registriamoci preliminarmente in Sonatype JIRA e apriamo un ticket per l'apertura del repository (per dettagli, vedere la sezione Creiamo un ticket su Sonatype JIRA). 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 Impostazione di GnuPG per firmare gli artefatti
  • Se usi la console Linux per generare la chiave GPG (gnupg/gnupg2), è necessario installare rng-tools per generare entropia. Altrimenti, la generazione della chiave potrebbe richiedere molto tempo.
  • Servizi di archiviazione chiavi GPG pubbliche

Al contenuto

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 — deploy
  • 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.
    Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central
  • 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 la firma dei commit, 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 variabile DEPLOY_TOKEN con trigger-token nel valore.

Al contenuto

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.

Al contenuto

Installiamo gitlab runner

  • Creiamo un nuovo gruppo runner
    sudo 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-deployer e aggiungiamo al gruppo runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • Aggiungiamo al file /etc/ssh/sshd_config la riga successiva
    AllowUsers root@* gitlab-deployer@127.0.0.1
  • Riavviando sshd
    systemctl 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

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

  • 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

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

  • 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

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

Al contenuto

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

Al contenuto

Configurazione di Maven

  • Accediamo con l'utente gitlab-deployer
    su 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 GitLab CI

Al contenuto

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 GitLab CI per il caricamento di un progetto Java su Maven Central

Al contenuto

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_XML le 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_XML le 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

Al contenuto

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

Al contenuto

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=true

Al contenuto

Progetto 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 gitlab-ci in cui ho collocato il template CI per i progetti java common.yml.

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_deploy

Al contenuto

Configurazione pom.xml

Questo argomento è descritto in modo molto dettagliato. Googolplex in Configurazione di Maven per la firma automatica e il caricamento degli artefatti nei repository snapshot e staging., 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
        
        true

Al contenuto

maven-javadoc-plugin

Generazione della javadoc per il progetto.

org.apache.maven.plugins
  maven-javadoc-plugin
  
    
      
        jar
      
      
      prepare-package
      
        
        true
        true
        
        false

Se 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}/javadoc

Al contenuto

maven-gpg-plugin

org.apache.maven.plugins
  maven-gpg-plugin
  
    
      sign-artifacts
      
      
      deploy
      
        sign

Al contenuto

nexus-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
      
        true

Dopo il caricamento, la versione snapshot/release è disponibile in repository di staging

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

Al contenuto

Risultato

Pubblicazione della versione SNAPSHOT

Durante la build del progetto, è possibile avviare manualmente il compito di caricamento della versione SNAPSHOT nel nexus

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

Quando viene avviato questo compito, si attiva il compito corrispondente nel progetto deploy (esempio).

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 1.0.0-SNAPSHOT.

Tutte le versioni snapshot possono essere eliminate dal repository sul sito oss.sonatype.org sotto il tuo account.

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

Al contenuto

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 (esempio).

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

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.

Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

Dopo il rilascio, dopo un po' gli artefatti si troveranno in Configurazione di GitLab CI per il caricamento di un progetto Java su Maven Central

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.

Al contenuto

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.

Al contenuto

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster