Configuración de GitLab CI para cargar un proyecto java en maven central

Este artículo está destinado a desarrolladores de Java que necesitan publicar rápidamente sus productos en los repositorios de Sonatype y/o Maven Central utilizando GitLab. En este artículo, hablaré sobre la configuración de gitlab-runner, gitlab-ci y el plugin de Maven para resolver esta tarea.

Requisitos previos:

  • Almacenamiento seguro de las claves mvn y GPG.
  • Ejecución segura de tareas CI públicas.
  • Carga de artefactos (release/snapshot) en repositorios públicos.
  • Verificación automática de versiones release para publicación en Maven Central.
  • Solución general para cargar artefactos en el repositorio para múltiples proyectos.
  • Sencillez y facilidad de uso.

Contenido

Información General

  • Se ha descrito detalladamente el mecanismo de publicación de artefactos en Maven Central a través del servicio de alojamiento de repositorios OSS de Sonatype en este artículo por el usuario Googolplex, por lo que haré referencia a este artículo en los lugares necesarios.
  • Primero, regístrate en Sonatype JIRA y crea un ticket para abrir el repositorio (lee más en la sección Crea un ticket en Sonatype JIRA). Después de abrir el repositorio, el par de login/contraseña de JIRA (más adelante, la cuenta de Sonatype) se utilizará para cargar artefactos en Sonatype Nexus.
  • A continuación, el proceso de generación de la clave GPG se describe de manera bastante escueta. Detalles en la sección Configuración de GnuPG para firmar artefactos
  • Si utilizas la consola de Linux para generar la clave GPG (gnupg/gnupg2), debes instalar rng-tools para generar entropía. De lo contrario, la generación de la clave puede tardar mucho.
  • Servicios de almacenamiento públicos de claves GPG

Al contenido

Configuración del proyecto de deploy en GitLab

  • En primer lugar, es necesario crear y configurar un proyecto donde se almacenará el pipeline para el despliegue de artefactos. Yo llamé a mi proyecto de manera simple — deploy
  • Después de crear el repositorio, es necesario restringir el acceso a la modificación del repositorio.
    Vamos al proyecto -> Configuración -> Repositorio -> Ramas protegidas. Eliminamos todas las reglas y agregamos una única regla con Wildcard * con permiso de push y merge solo para usuarios con el rol de Mantenedor. Esta regla funcionará para todos los usuarios tanto de este proyecto como del grupo al que pertenece este proyecto.
    Configuración de GitLab CI para cargar un proyecto java en maven central
  • Si hay varios mantenedores, la mejor solución será restringir el acceso al proyecto en general.
    Vamos al proyecto -> Configuración -> General -> Visibilidad, características del proyecto, permisos y configuramos la Visibilidad del proyecto en el valor Privado.
    Mi proyecto es de acceso público, ya que utilizo mi propio GitLab Runner y solo yo tengo acceso para modificar el repositorio. Además, no es de mi interés revelar información privada en los registros de pipeline públicos.
  • Endurecimiento de las reglas para modificar el repositorio
    Vamos al proyecto -> Configuración -> Repositorio -> Reglas de push y establecemos las banderas Restricción de committer, Comprobar si el autor es un usuario de GitLab. También recomiendo configurar la firma de commits, y activar la opción Rechazar commits sin firmar.
  • A continuación, es necesario configurar un disparador para iniciar tareas
    Vamos al proyecto -> Configuración -> CI / CD -> Disparadores de pipeline y creamos un nuevo token de disparo
    Este token se puede agregar de inmediato a la configuración global de variables para el grupo de proyectos.
    Vamos al grupo -> Configuración -> CI / CD -> Variables y agregamos la variable DEPLOY_TOKEN con el token de disparo en el valor.

Al contenido

GitLab Runner

En esta sección se describe la configuración para iniciar tareas de despliegue utilizando un runner propio (Específico) y un runner público (Compartido).

Runner específico

Uso runners propios porque, ante todo, es conveniente, rápido y económico.
Para el runner, recomiendo un VDS de Linux con 1 CPU, 2 GB de RAM, 20 GB de HDD. El costo es de aproximadamente 3000₽ al año.

Mi runner

Para el runner, elegí un VDS con 4 CPU, 4 GB de RAM, 50 GB de SSD. Costó alrededor de 11000₽ y no me he arrepentido ni una vez.
En total tengo 7 máquinas. 5 en Aruba y 2 en Ihor.

Así que tenemos un runner. Ahora vamos a configurarlo.
Ingresamos a la máquina por SSH e instalamos java, git, maven, gnupg2.

Al contenido

Instalamos gitlab runner

  • Creamos un nuevo grupo runner
    sudo groupadd runner
  • Creamos un directorio para el caché de maven y asignamos los derechos del grupo runner
    Este paso se puede omitir si no planeas ejecutar varios runners en una sola máquina.
    mkdir -p /usr/cache/.m2/repository
    chown -R :runner /usr/cache
    chmod -R 770 /usr/cache
  • Creamos el usuario gitlab-deployer y lo añadimos al grupo runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • Agregamos a archivo /etc/ssh/sshd_config la siguiente línea
    PermitirUsuarios root@* gitlab-deployer@127.0.0.1
  • Reiniciando sshd
    systemctl restart sshd
  • Estableciendo contraseña para el usuario gitlab-deployer (puede ser simple, ya que hay una restricción para localhost)
    passwd gitlab-deployer
  • Instalando 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
  • Accedemos al sitio gitlab.com -> desplegar-proyecto -> Configuración -> CI/CD -> Runners -> Runners específicos y copiamos el token de registro

Captura de pantalla

Configuración de GitLab CI para cargar un proyecto java en maven central

  • Registrando runner
    gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml

El proceso

Plataforma de ejecución arch=amd64 os=linux pid=17594 revision=3001a600 version=11.10.0
Ejecutando en modo sistema.
Por favor, introduzca la URL coordinador de gitlab-ci (por ejemplo, https://gitlab.com/):
https://gitlab.com/
Por favor, introduzca el token de gitlab-ci para este runner:
REGISTRATION_TOKEN
Por favor, introduzca la descripción de gitlab-ci para este runner:
[ih1174328.vds.myihor.ru]: Desplegar Runner
Por favor, introduzca las etiquetas de gitlab-ci para este runner (separadas por comas):
desplegar
Registrando runner... succeeded                     runner=ZvKdjJhx
Por favor, introduzca el executor: docker-ssh, parallels, virtualbox, docker-ssh+machine, kubernetes, docker, ssh, docker+machine, shell:
shell
Runner registrado con éxito. Siéntase libre de iniciarlo, pero si ya está en ejecución, ¡la configuración debería recargarse automáticamente!
  • Verificando que el runner esté registrado. Accedemos al sitio gitlab.com -> desplegar-proyecto -> Configuración -> CI/CD -> Runners -> Runners específicos -> Runners activados para este proyecto

Captura de pantalla

Configuración de GitLab CI para cargar un proyecto java en maven central

  • Añadimos separado servicio /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
  • Iniciamos el servicio.
    systemctl enable gitlab-deployer.service
    systemctl start gitlab-deployer.service
    systemctl status gitlab-deployer.service
  • Verificando que el runner esté en ejecución.

Ejemplo

Configuración de GitLab CI para cargar un proyecto java en maven central

Al contenido

Generación de claves GPG

  • Desde esta misma máquina, accedemos por ssh con el usuario gitlab-deployer (esto es importante para generar la clave GPG)
    ssh gitlab-deployer@127.0.0.1
  • Generamos la clave respondiendo a las preguntas. Usé mi propio nombre y correo.
    Asegúrese de especificar una contraseña para la clave. Esta clave se usará para firmar los artefactos.
    gpg --gen-key 
  • Verificamos.
    gpg --list-keys -a
    /home/gitlab-deployer/.gnupg/pubring.gpg
    ----------------------------------------
    pub   4096R/00000000 2019-04-19
    uid                  Petruha Petrov 
    sub   4096R/11111111 2019-04-19
  • Subimos nuestra clave pública al servidor de claves
    gpg --keyserver keys.gnupg.net --send-key 00000000
    gpg: enviando clave 00000000 al servidor hkp keys.gnupg.net

Al contenido

Configuración de Maven

  • Accedemos como usuario gitlab-deployer
    su gitlab-deployer 
  • Creamos el directorio maven repositorio y lo vinculamos con la caché (no se equivoque)
    Este paso se puede omitir si no planea ejecutar varios runners en la misma máquina.
    mkdir -p ~\/ .m2\/ repository
    ln -s \/ usr\/ cache\/ .m2\/ repository \/ home\/ gitlab-deployer\/ .m2\/ repository
  • Creando la clave maestra
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci\/mpsur\/73tR2I=}
  • Creando el archivo ~\/ .m2\/ settings-security.xml
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci\/mpsur\/73tR2I=}
  • Cifrando la contraseña de la cuenta de Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G\/kR4R8Z0WBgcDBgi7d12S\/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Creando el archivo ~\/ .m2\/ settings.xml
    env
            
                true
            
            
                GPG_SECRET_KEY_PASSPHRASE
            
        
    
    
        
            sonatype
            SONATYPE_USERNAME
            {98Wv5+u+Tn0HX2z5G\/kR4R8Z0WBgcDBgi7d12S\/un+SCU7uxzaZGGmJ8Cu9pAZ2J}

donde,
GPG_SECRET_KEY_PASSPHRASE — contraseña de la clave GPG
SONATYPE_USERNAME — nombre de usuario de la cuenta de Sonatype

Con esto, la configuración del runner está completa, podemos pasar a la sección GitLab CI

Al contenido

Runner compartido

Generación de claves GPG

  • Primero, necesitamos crear una clave GPG. Para ello, instalamos gnupg.
    yum install -y gnupg
  • Generamos la clave respondiendo a las preguntas. Usé mi nombre y correo electrónico personales. Asegúrate de indicar una contraseña para la clave.
    gpg --gen-key 
  • Mostrando información sobre la clave
    gpg --list-keys -a
    pub   rsa3072 2019-04-24 [SC] [expires: 2021-04-23]
      2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    uid           [ultimate] tttemp 
    sub   rsa3072 2019-04-24 [E] [expires: none]
  • Subimos nuestra clave pública al servidor de claves
    gpg --keyserver keys.gnupg.net --send-key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    gpg: enviando la clave 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 al servidor hkp keys.gnupg.net
  • Obteniendo la clave privada
    gpg --export-secret-keys --armor 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    -----BEGIN PGP PRIVATE KEY BLOCK-----
    lQWGBFzAqp8BDADN41CPwJ/gQwiKEbyA902DKw/WSB1AvZQvV/ZFV77xGeG4K7k5
    ...
    =2Wd2
    -----END PGP PRIVATE KEY BLOCK-----
  • Vamos a la configuración del proyecto -> Configuración -> CI / CD -> Variables y guardamos la clave privada en la variable GPG_SECRET_KEY
    Configuración de GitLab CI para cargar un proyecto java en maven central

Al contenido

Configuración de Maven

  • Creando la clave maestra
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci\/mpsur\/73tR2I=}
  • Vamos a la configuración del proyecto -> Configuración -> CI / CD -> Variables y guardamos en la variable SETTINGS_SECURITY_XML las siguientes líneas:
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci\/mpsur\/73tR2I=}
  • Cifrando la contraseña de la cuenta de Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G\/kR4R8Z0WBgcDBgi7d12S\/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Vamos a la configuración del proyecto -> Configuración -> CI / CD -> Variables y guardamos en la variable SETTINGS_XML las siguientes líneas:
    env
            
                true
            
            
                GPG_SECRET_KEY_PASSPHRASE
            
        
    
    
        
            sonatype
            sonatype_username
            {98Wv5+u+Tn0HX2z5G\/kR4R8Z0WBgcDBgi7d12S\/un+SCU7uxzaZGGmJ8Cu9pAZ2J}

donde,
GPG_SECRET_KEY_PASSPHRASE — contraseña de la clave GPG
SONATYPE_USERNAME — nombre de usuario de la cuenta de Sonatype

Al contenido

Implementar la imagen de Docker

  • Creamos un Dockerfile bastante simple para ejecutar tareas de implementación con la versión correcta de Java. A continuación, se muestra un ejemplo para alpine.
    DE 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/
  • Construimos un contenedor para su proyecto
    docker build -t registry.gitlab.com/group/deploy .
  • Autenticamos y subimos el contenedor al registro.
    docker login -u USER -p PASSWORD registry.gitlab.com
    docker push registry.gitlab.com/group/deploy

Al contenido

GitLab CI

Implementar el proyecto

Añadimos el archivo .gitlab-ci.yml a la raíz del proyecto de despliegue
El script presenta dos tareas mutuamente excluyentes para el despliegue. Specific Runner o Shared Runner, respectivamente.

.gitlab-ci.yml

stages:
  - deploy

Specific Runner:
  extends: .java_deploy_template
  # La tarea se ejecutará en su shell-runner
  tags:
    - deploy

Shared Runner:
  extends: .java_deploy_template
  # La tarea se ejecutará en un docker-runner público
  tags:
    - docker
  # Imagen de la sección GitLab Runner -> Shared Runner -> Docker
  image: registry.gitlab.com/group/deploy-project:latest
  before_script:
    # Importamos la clave GPG
    - printf "${GPG_SECRET_KEY}" | gpg --batch --import
    # Guardamos la configuración de maven
    - printf "${SETTINGS_SECURITY_XML}" > ~/.m2/settings-security.xml
    - printf "${SETTINGS_XML}" > ~/.m2/settings.xml

.java_deploy_template:
  stage: deploy
  # La tarea se activará por el trigger si se pasa la variable DEPLOY con el valor java
  only:
    variables:
    - $DEPLOY == "java"
  variables:
    # desactivamos la clonación del proyecto actual
    GIT_STRATEGY: none
  script:
    # Permitimos el almacenamiento de la contraseña en texto claro
    - git config --global credential.helper store
    # Guardamos las credenciales temporales del usuario gitlab-ci-token
    # El token funciona para todos los proyectos públicos en gitlab.com y para proyectos del grupo
    - echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
    # Limpiamos completamente el directorio actual
    - rm -rf .* *
    # Clonamos el proyecto que vamos a desplegar en Sonatype Nexus
    - git clone ${DEPLOY_CI_REPOSITORY_URL} .
    # Cambiamos al commit deseado
    - git checkout ${DEPLOY_CI_COMMIT_SHA} -f
    # Si al menos un pom.xml contiene el parámetro autoReleaseAfterClose, fallamos la construcción.
    # De lo contrario, hay riesgo de subir artefactos crudos a maven central
    - >
      for pom in $(find . -name pom.xml); do
        if [[ $(grep -q autoReleaseAfterClose "$pom" && echo $?) == 0 ]]; then
          echo "El archivo $pom contiene un ajuste prohibido: ";
          exit 1;
        fi;
      done
    # Si el parámetro DEPLOY_CI_COMMIT_TAG está vacío, forzamos una versión 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
    # Ejecutamos la tarea de construcción y despliegue de artefactos
    - mvn clean deploy -DskipTests=true

Al contenido

Proyecto Java

En proyectos de Java que se van a cargar en repositorios públicos, es necesario agregar 2 pasos para cargar las versiones Release y Snapshot.

.gitlab-ci.yml

stages:
  - build
  - test
  - verify
  - deploy



Release:
  extends: .trigger_deploy
  # Ejecutar la tarea solo por etiqueta.
  only:
    - tags

Snapshot:
  extends: .trigger_deploy
  # Ejecutar manualmente la tarea para publicar la versión SNAPSHOT
  when: manual
  # No ejecutar la tarea si se ha asignado una etiqueta.
  except:
    - tags

.trigger_deploy:
  stage: deploy
  variables:
    # Desactivar la clonación del proyecto actual
    GIT_STRATEGY: none
    # Enlace al trigger de tarea de despliegue
    URL: "https://gitlab.com/api/v4/projects//trigger/pipeline"
    # Variables para la tarea de despliegue
    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:
    # No uso cURL, ya que con los flags --fail --show-error
    # no imprime el cuerpo de la respuesta si el código HTTP es 400 o más
    - wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}

En esta solución, fui un poco más allá y decidí utilizar una plantilla CI única para proyectos de Java.

Más detalles

Creé un proyecto separado gitlab-ci en el que coloqué la plantilla CI para proyectos de Java common.yml.

common.yml

etapas:
  - construcción
  - prueba
  - verificación
  - implementación

variables:
  SONAR_ARGS: "
  -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA} 
  -Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME} 
  "

.build_java_project:
  etapa: construcción
  etiquetas:
    - touchbit-shell
  variables:
    SKIP_TEST: "false"
  script:
    - mvn clean
    - mvn package -DskipTests=${SKIP_TEST}
  artefactos:
    cuando: siempre
    expirar_en: 30 días
    rutas:
      - "*\/target\/reports"

.build_sphinx_doc:
  etapa: construcción
  etiquetas:
    - touchbit-shell
  variables:
    DOCKERFILE: .indirect\/docs\/Dockerfile
  script:
    - docker build --no-cache -t ${CI_PROJECT_NAME}\/doc -f ${DOCKERFILE} .

.junit_module_test_run:
  etapa: prueba
  etiquetas:
    - touchbit-shell
  variables:
    MÓDULO: ""
  script:
    - cd ${MÓDULO}
    - mvn test
  artefactos:
    cuando: siempre
    expirar_en: 30 días
    rutas:
      - "*\/target\/reports"

.junit_test_run:
  etapa: prueba
  etiquetas:
    - touchbit-shell
  script:
    - mvn test
  artefactos:
    cuando: siempre
    expirar_en: 30 días
    rutas:
    - "*\/target\/reports"

.sonar_review:
  etapa: verificación
  etiquetas:
    - touchbit-shell
  dependencias: []
  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:
  etapa: implementación
  etiquetas:
    - touchbit-shell
  variables:
    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:
  extiende: .trigger_deploy
  solo:
    - etiquetas

.trigger_snapshot_deploy:
  extiende: .trigger_deploy
  cuando: manual
  excepto:
    - etiquetas

Como resultado, el archivo .gitlab-ci.yml en los propios proyectos Java es bastante compacto y conciso.

.gitlab-ci.yml

incluir: https://gitlab.com/TouchBIT/gitlab-ci/raw/master/common.yml

Shields4J:
  extiende: .build_java_project

Documentación Sphinx:
  extiende: .build_sphinx_doc
  variables:
    DOCKERFILE: .docs/Dockerfile

Revisión de Sonar:
  extiende: .sonar_review
  dependencias:
    - Shields4J

Liberación:
  extiende: .trigger_release_deploy

Instantánea:
  extiende: .trigger_snapshot_deploy

Al contenido

Configuración de pom.xml

Este tema está descrito con mucho detalle. Googolplex en Configuración de Maven para la firma automática y la carga de artefactos en depósitos de instantáneas y staging., por lo tanto, describiré algunos matices del uso de complementos. También explicaré cómo se puede utilizar de manera fácil y sin complicaciones. nexus-staging-maven-plugin, si no desea o no puede usar org.sonatype.oss:oss-parent como padre para su proyecto.

maven-install-plugin

Instala módulos en el repositorio local.
Es muy útil para verificar localmente soluciones en otros proyectos, así como para el uso de sumas de verificación.

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 contenido

maven-javadoc-plugin

Generación de javadoc para el proyecto.

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

Si tienes un módulo que no contiene java (por ejemplo, solo recursos)
O si no deseas generar javadoc en absoluto, aquí tienes ayuda maven-jar-plugin

org.apache.maven.plugins
  maven-jar-plugin
  
    
      empty-javadoc-jar
      generate-resources
      
        jar
      
      
        javadoc
        ${basedir}/javadoc

Al contenido

maven-gpg-plugin

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

Al contenido

nexus-staging-maven-plugin

Configuración:


  
    
      
      
        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
      Repositorio de Snapshot de Nexus
      https://oss.sonatype.org/content/repositories/snapshots/
    
    
      sonatype
      Repositorio de Release de Nexus
      https://oss.sonatype.org/service/local/staging/deploy/maven2/

Si tiene un proyecto multimódulo y no necesita cargar un módulo específico en el repositorio, debe agregar en el pom.xml de este módulo nexus-staging-maven-plugin con la bandera skipNexusStagingDeployMojo

org.sonatype.plugins
      nexus-staging-maven-plugin
      
        true

Después de cargar la versión snapshot/release, estarán disponibles en repositorio de staging

SonatypeNexus
    https://oss.sonatype.org/content/groups/staging/
    

Más ventajas

  • Una lista muy completa de objetivos para trabajar con el repositorio de nexus (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
  • Verificación automática de la versión release para su carga en maven central

Al contenido

Resultado

Publicación de la versión SNAPSHOT

Al construir el proyecto hay la posibilidad de ejecutar manualmente la tarea de cargar la versión SNAPSHOT en nexus

Configuración de GitLab CI para cargar un proyecto java en maven central

Al ejecutar esta tarea, se activa la tarea correspondiente en el proyecto deploy (ejemplo).

Registro recortado

Ejecutando con gitlab-runner 11.10.0 (3001a600)
  en el corredor de despliegue JSKWyxUw
Usando el ejecutor Shell...
Ejecutando en ih1174328.vds.myihor.ru...
Omitiendo configuración del repositorio de Git
Omitiendo verificación de Git
Omitiendo configuración de submódulos de 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} .
Clonando en 'shields4j'...
$ git checkout ${DEPLOY_CI_COMMIT_SHA}
Nota: comprobando '850f86aa317194395c5387790da1350e437125a7'.
Estás en un estado de 'HEAD desapegado'. Puedes mirar a tu alrededor, hacer cambios experimentales y confirmarlos, y puedes descartar cualquier confirmación que hagas en este estado sin afectar ninguna rama al realizar otro checkout.
Si quieres crear una nueva rama para retener los commits que creas, puedes hacerlo (ahora o después) usando -b con el comando checkout nuevamente. Ejemplo:
  git checkout -b nombre_nueva_rama
El HEAD ahora está en 850f86a... omitir prueba de despliegue test-core
$ for pom in $(find . -name pom.xml); do # comando de varias líneas colapsado
$ if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then # comando de varias líneas colapsado
[INFO] Escaneando proyectos...
[INFO] Inspeccionando la construcción con un total de 4 módulos...
[INFO] Instalando características de Nexus Staging:
[INFO]   ... un total de 4 ejecuciones de maven-deploy-plugin reemplazadas con nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Orden de construcción del Reactor:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Cliente Shields4J                                                   [jar]
[INFO] Listener TestNG                                                    [jar]
[INFO] 
[INFO] -----------------------------
[INFO] Construyendo Shields4J 1.0.0                                           [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- versions-maven-plugin:2.5:set (default-cli) @ shields4j-parent ---
[INFO] Buscando la raíz del agregador local...
[INFO] Raíz de agregación local: /home/gitlab-deployer/JSKWyxUw/0/TouchBIT/deploy/shields4j
[INFO] Procesando el cambio de org.touchbit.shields4j:shields4j-parent:1.0.0 -> 1.0.0-SNAPSHOT
[INFO] Procesando org.touchbit.shields4j:shields4j-parent
[INFO]     Actualizando proyecto org.touchbit.shields4j:shields4j-parent
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO] 
[INFO] Procesando org.touchbit.shields4j:client
[INFO]     Actualizando padre org.touchbit.shields4j:shields4j-parent
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO]     Actualizando dependencia org.touchbit.shields4j:test-core
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO] 
[INFO] Procesando org.touchbit.shields4j:test-core
[INFO]     Actualizando padre org.touchbit.shields4j:shields4j-parent
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO] 
[INFO] Procesando org.touchbit.shields4j:testng
[INFO]     Actualizando padre org.touchbit.shields4j:shields4j-parent
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO]     Actualizando dependencia org.touchbit.shields4j:client
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO]     Actualizando dependencia org.touchbit.shields4j:test-core
[INFO]         de la versión 1.0.0 a 1.0.0-SNAPSHOT
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Resumen del Reactor:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... ÉXITO [  0.992 s]
[INFO] test-core .......................................... OMITIDO
[INFO] Cliente Shields4J ................................... OMITIDO
[INFO] Listener TestNG 1.0.0 .............................. OMITIDO
[INFO] ------------------------------------------------------------------------
[INFO] CONSTRUCCIÓN EXITOSA
[INFO] ------------------------------------------------------------------------
[INFO] Tiempo total: 2.483 s
[INFO] Terminado en: 2019-04-21T02:40:42+03:00
[INFO] ------------------------------------------------------------------------
$ mvn clean deploy -DskipTests=${SKIP_TESTS}
[INFO] Escaneando proyectos...
[INFO] Inspeccionando la construcción con un total de 4 módulos...
[INFO] Instalando características de Nexus Staging:
[INFO]   ... un total de 4 ejecuciones de maven-deploy-plugin reemplazadas con nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Orden de construcción del Reactor:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Cliente Shields4J                                                   [jar]
[INFO] Listener TestNG                                                    [jar]
[INFO] 
[INFO] -----------------------------
[INFO] Construyendo Shields4J 1.0.0-SNAPSHOT                                  [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
...
ELIMINADO
...
[INFO]  * El despliegue masivo de artefactos de instantáneas recogidos localmente finalizó.
[INFO] El despliegue remoto finalizó con éxito.
[INFO] ------------------------------------------------------------------------
[INFO] Resumen del Reactor:
[INFO] 
[INFO] Shields4J 1.0.0-SNAPSHOT ........................... ÉXITO [  2.375 s]
[INFO] test-core .......................................... ÉXITO [  3.929 s]
[INFO] Cliente Shields4J ................................... ÉXITO [  3.815 s]
[INFO] Listener TestNG 1.0.0-SNAPSHOT ..................... ÉXITO [ 36.134 s]
[INFO] ------------------------------------------------------------------------
[INFO] CONSTRUCCIÓN EXITOSA
[INFO] ------------------------------------------------------------------------
[INFO] Tiempo total: 47.629 s
[INFO] Terminado en: 2019-04-21T02:41:32+03:00
[INFO] ------------------------------------------------------------------------

Como resultado, se ha cargado una versión en nexus 1.0.0-SNAPSHOT.

Todas las versiones snapshot se pueden eliminar del repositorio en el sitio web oss.sonatype.org con su cuenta.

Configuración de GitLab CI para cargar un proyecto java en maven central

Al contenido

Publicación de la versión release

Al instalar la etiqueta, se activa automáticamente la tarea correspondiente en el proyecto de despliegue para cargar la versión de lanzamiento en nexus (ejemplo).

Configuración de GitLab CI para cargar un proyecto java en maven central

Lo más agradable es que se activa automáticamente el cierre del lanzamiento en nexus.

[INFO] Realizando el staging remoto...
[INFO] 
[INFO]  * Staging remoto en el perfil de staging ID "9043b43f77dcc9"
[INFO]  * Repositorio de staging creado con ID "orgtouchbit-1037".
[INFO]  * Repositorio de staging en https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1037
[INFO]  * Subiendo artefactos localmente staged al perfil org.touchbit
[INFO]  * La carga de artefactos localmente staged ha finalizado.
[INFO]  * Cerrando el repositorio de staging con ID "orgtouchbit-1037".
Esperando que la operación se complete...
.........
[INFO] Se han preparado 1 repositorio de forma remota, finalizado con éxito.
[INFO] ------------------------------------------------------------------------
[INFO] Resumen del Reactor:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... ÉXITO [  9.603 s]
[INFO] test-core .......................................... ÉXITO [  3.419 s]
[INFO] Cliente Shields4J ................................... ÉXITO [  9.793 s]
[INFO] Listener TestNG 1.0.0 .............................. ÉXITO [01:23 min]
[INFO] ------------------------------------------------------------------------
[INFO] CONSTRUCCIÓN EXITOSA
[INFO] ------------------------------------------------------------------------
[INFO] Tiempo total: 01:47 min
[INFO] Finalizado en: 2019-04-21T04:05:46+03:00
[INFO] ------------------------------------------------------------------------

Y si algo sale mal, la tarea definitivamente fallará

[INFO] Realizando una subida remota a staging...
[INFO] 
[INFO]  * Subida remota al perfil de staging ID "9043b43f77dcc9"
[INFO]  * Se creó el repositorio de staging con ID "orgtouchbit-1038".
[INFO]  * Repositorio de staging en https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1038
[INFO]  * Subiendo artefactos de staging localmente al perfil org.touchbit
[INFO]  * La subida de artefactos de staging localizados ha finalizado.
[INFO]  * Cerrando el repositorio de staging con ID "orgtouchbit-1038".
Esperando que la operación se complete...
.......
[ERROR] Error de regla al intentar cerrar el repositorio de staging con ID "orgtouchbit-1039".
[ERROR] 
[ERROR] Informe de Fallos de Reglas de Nexus Staging
[ERROR] ==================================
[ERROR] 
[ERROR] Fallos en el repositorio "orgtouchbit-1039"
[ERROR]   Fallos de la regla "signature-staging"
[ERROR]     * No se encontró la clave pública: La clave con id: (1f42b618d1cbe1b5) no pudo ser localizada en http://keys.gnupg.net:11371/. Sube tu clave pública y vuelve a intentar la operación.
...
[ERROR] Limpiando el directorio local de staging después de un fallo de regla durante el cierre de los repositorios de staging: [orgtouchbit-1039]
[ERROR]  * Eliminando el contexto 9043b43f77dcc9.properties
[ERROR] Limpiando los repositorios de staging remotos después de un fallo de regla durante el cierre de los repositorios de staging: [orgtouchbit-1039]
[ERROR]  * Eliminando el repositorio de staging fallido con ID "orgtouchbit-1039" (Fallo de regla durante el cierre de los repositorios de staging: [orgtouchbit-1039]).
[ERROR] La subida remota finalizó con un fallo: ¡Fallo en las reglas de staging!
[INFO] ------------------------------------------------------------------------
[INFO] Resumen del Reactor:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... ÉXITO [  4.073 s]
[INFO] test-core .......................................... ÉXITO [  2.788 s]
[INFO] Cliente Shields4J .................................. ÉXITO [  3.962 s]
[INFO] Listener de TestNG 1.0.0 .......................... FALLA [01:07 min]
[INFO] ------------------------------------------------------------------------
[INFO] FALLA EN LA CONSTRUCCIÓN
[INFO] ------------------------------------------------------------------------

Como resultado, solo nos queda una elección. O eliminar esta versión o publicarla.

Configuración de GitLab CI para cargar un proyecto java en maven central

Después del lanzamiento, después de un tiempo, los artefactos estarán en Configuración de GitLab CI para cargar un proyecto java en maven central

off-topic

Fue una revelación para mí que Maven indexa otros repositorios públicos.
Tuve que agregar un robots.txt, ya que había indexado mi antiguo repositorio.

Al contenido

Conclusión

Lo que tenemos

  • Un proyecto de deploy separado donde se pueden implementar varias tareas de CI para cargar artefactos en repositorios públicos para diferentes lenguajes de desarrollo.
  • El proyecto de deploy está aislado de interferencias externas y solo puede ser modificado por usuarios con rol de Owner y Maintainer.
  • Un Runner específico separado con caché 'caliente' para ejecutar solo tareas de deploy.
  • Publicación de versiones snapshot/release en el repositorio público.
  • Comprobación automática de la versión de release para su preparación para la publicación en Maven Central.
  • Protección contra la publicación automática de versiones 'crudas' en Maven Central.
  • Compilación y publicación de versiones snapshot 'con un clic'.
  • Un único repositorio para obtener versiones snapshot/release.
  • Pipeline general para la construcción/prueba/publicación de un proyecto Java.

Configurar GitLab CI no es un tema tan complicado como parece a primera vista. Es suficiente con configurar CI "llave en mano" un par de veces y ya no serás un principiante en esta materia. Además, la documentación de GitLab es bastante extensa. No temas dar el primer paso. El camino se crea al andar (no recuerdo quién lo dijo 🙂 ).

Estaré encantado de recibir comentarios.

En el próximo artículo hablaré sobre cómo configurar GitLab CI para ejecutar tareas de manera concurrente con pruebas de integración (iniciando los servicios a probar con docker-compose), si solo dispones de un shell runner.

Al contenido

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster