Configuració de GitLab CI per carregar un projecte java a Maven Central

Aquest article està destinat als desenvolupadors de Java que necessiten publicar ràpidament els seus productes als repositoris centrals de sonatype i/o maven mitjançant GitLab. En aquest article, parlaré de la configuració de gitlab-runner, gitlab-ci i maven-plugin per resoldre aquest problema.

Requisits previs:

  • Emmagatzematge segur de claus mvn i GPG.
  • Execució segura de les tasques públiques de CI.
  • Càrrega d'artefactes (alliberament/snapshot) als repositoris públics.
  • Comprovació automàtica de les versions de llançament per a la seva publicació a maven central.
  • Una solució general per carregar artefactes a un repositori per a diversos projectes.
  • Simplicitat i facilitat d'ús.

Contingut

Informació general

  • Ja es descriu una descripció detallada del mecanisme per publicar artefactes a Maven Central mitjançant el servei d'allotjament del repositori Sonatype OSS a Aquest article usuari Googleolplex, així que em referiré a aquest article als llocs adequats.
  • Preinscripció a Sonatip JIRA i inicieu un bitllet per obrir el repositori (per a més detalls, llegiu la secció Creeu un bitllet Sonatype JIRA). Després d'obrir el repositori, s'utilitzarà el parell d'inici de sessió/contrasenya de JIRA (d'ara endavant, el compte Sonatype) per carregar artefactes al nexe Sonatype.
  • A més, el procés de generació d'una clau GPG es descriu molt secament. Consulteu la secció per a més detalls. Configuració de GnuPG per signar artefactes
  • Si utilitzeu la consola Linux per generar una clau GPG (gnupg/gnupg2), haureu d'instal·lar rng-tools per generar entropia. En cas contrari, la generació de claus pot trigar molt de temps.
  • Serveis d'emmagatzematge públic claus GPG

Al contingut

Configuració d'un projecte de desplegament a GitLab

  • En primer lloc, heu de crear i configurar un projecte en el qual s'emmagatzemarà la canalització per al desplegament d'artefactes. Vaig anomenar el meu projecte senzillament i sense complicacions - desplegar
  • Després de crear el repositori, heu de restringir l'accés per canviar-lo.
    Aneu al projecte -> Configuració -> Repositori -> Branques protegides. Suprimim totes les regles i afegim una única regla amb comodí * amb el dret d'impulsar i combinar només per als usuaris amb la funció de Mantenidors. Aquesta regla funcionarà per a tots els usuaris tant d'aquest projecte com del grup al qual pertany aquest projecte.
    Configuració de GitLab CI per carregar un projecte java a Maven Central
  • Si hi ha diversos mantenedors, la millor solució seria restringir l'accés al projecte en principi.
    Aneu al projecte -> Configuració -> General -> Visibilitat, característiques del projecte, permisos i configureu la visibilitat del projecte a Privat.
    Tinc un projecte en accés públic, ja que faig servir el meu propi GitLab Runner i només tinc accés per modificar el repositori. Bé, en realitat no és del meu interès mostrar informació privada als registres de canalització públics.
  • Enduriment de les regles per canviar el repositori
    Aneu al projecte -> Configuració -> Repositori -> Regles Push i configureu la restricció de Committer de marques, comproveu si l'autor és un usuari de GitLab. També recomano la configuració signatura de compromís, i establiu el senyalador Rebutja les confirmacions sense signar.
  • A continuació, heu de configurar un activador per executar tasques
    Aneu a Projecte -> Configuració -> CI / CD -> Activadors de Pipeline i creeu un nou token d'activació
    Aquest testimoni es pot afegir immediatament a la configuració general de variables per a un grup de projectes.
    Aneu al grup -> Configuració -> CI / CD -> Variables i afegiu una variable DEPLOY_TOKEN amb un token disparador al valor.

Al contingut

GitLab Runner

Aquesta secció descriu la configuració per executar tasques en desplegament mitjançant l'executor natiu (específic) i públic (compartit).

Corredor específic

Jo faig servir els meus propis corredors, perquè primer de tot és còmode, ràpid, barat.
Per als corredors, recomano Linux VDS amb 1 CPU, 2 GB de RAM, 20 GB de disc dur. Preu d'emissió ~ 3000₽ per any.

El meu corredor

Per al corredor vaig prendre VDS 4 CPU, 4 GB de RAM, 50 GB SSD. Va costar ~11000₽ i mai no es va penedir.
Tinc un total de 7 màquines. 5 a aruba i 2 a ihor.

Així doncs, tenim un corredor. Ara el configurarem.
Anem a la màquina mitjançant SSH i instal·lem java, git, maven, gnupg2.

Al contingut

Instal·lació de gitlab runner

  • Crea un grup nou runner
    sudo groupadd runner
  • Creeu un directori per a la memòria cau de maven i assigneu drets de grup runner
    Podeu ometre aquest pas si no teniu previst executar diversos corredors a la mateixa màquina.

    mkdir -p /usr/cache/.m2/repository
    chown -R :runner /usr/cache
    chmod -R 770 /usr/cache
  • Crear un usuari gitlab-deployer i afegir al grup runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • Afegeix al fitxer /etc/ssh/sshd_config línia següent
    AllowUsers root@* [email protected]
  • Reinicieu sshd
    systemctl restart sshd
  • Establiu una contrasenya per a l'usuari gitlab-deployer (pot ser senzill, ja que hi ha una restricció per a localhost)
    passwd gitlab-deployer
  • Instal·leu 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
  • Aneu a gitlab.com -> deploy-project -> Configuració -> CI/CD -> Corredors -> Corredors específics i copieu el testimoni de registre

Pantalla

Configuració de GitLab CI per carregar un projecte java a Maven Central

  • Inscripció del corredor
    gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml

procés

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!

  • Comprova que el corredor estigui inscrit. Aneu a gitlab.com -> deploy-project -> Configuració -> CI/CD -> Corredors -> Corredors específics -> Corredors activats per a aquest projecte

Pantalla

Configuració de GitLab CI per carregar un projecte java a Maven Central

  • Afegiu separat servei /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
  • Comencem el servei.
    systemctl enable gitlab-deployer.service
    systemctl start gitlab-deployer.service
    systemctl status gitlab-deployer.service
  • Comprova que el corredor està corrent.

Exemple

Configuració de GitLab CI per carregar un projecte java a Maven Central

Al contingut

Generació de claus GPG

  • Des de la mateixa màquina anem via ssh sota l'usuari gitlab-deployer (això és important per a la generació de claus GPG)

    ssh [email protected]

  • Generem una clau responent preguntes. Vaig utilitzar el meu propi nom i correu electrònic.
    Assegureu-vos d'especificar la contrasenya de la clau. Els artefactes es signaran amb aquesta clau.

    gpg --gen-key 

  • Comprovació

    gpg --list-keys -a
    /home/gitlab-deployer/.gnupg/pubring.gpg
    ----------------------------------------
    pub   4096R/00000000 2019-04-19
    uid                  Petruha Petrov <[email protected]>
    sub   4096R/11111111 2019-04-19

  • Penjant la nostra clau pública al servidor de claus

    gpg --keyserver keys.gnupg.net --send-key 00000000
    gpg: sending key 00000000 to hkp server keys.gnupg.net

Al contingut

Configuració de Maven

  • Passem per sota de l'usuari gitlab-deployer
    su gitlab-deployer 
  • Creeu un directori maven repositori i enllaça amb la memòria cau (no t'equivoquis)
    Aquest pas es pot saltar si no teniu previst executar diversos corredors a la mateixa màquina.

    mkdir -p ~/.m2/repository
    ln -s /usr/cache/.m2/repository /home/gitlab-deployer/.m2/repository
  • Creeu una clau mestra
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Creeu el fitxer ~/.m2/settings-security.xml
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Xifrat de la contrasenya des del compte Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Creeu el fitxer ~/.m2/settings.xml
    <settings>  
    <profiles>
        <profile>
            <id>env</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.passphrase>GPG_SECRET_KEY_PASSPHRASE</gpg.passphrase>
            </properties>
        </profile>
    </profiles>
    <servers>
        <server>
            <id>sonatype</id>
            <username>SONATYPE_USERNAME</username>
            <password>{98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}</password>
        </server>
    </servers>
    </settings>

on,
GPG_SECRET_KEY_PASSPHRASE: contrasenya de clau GPG
SONATYPE_USERNAME: inici de sessió al compte de sonatype

Això completa la configuració del corredor, podeu passar a la secció GitLab CI

Al contingut

Corredor compartit

Generació de claus GPG

  • En primer lloc, heu de crear una clau GPG. Per fer-ho, instal·leu gnupg.

    yum install -y gnupg

  • Generem una clau responent preguntes. Vaig utilitzar el meu propi nom i correu electrònic. Assegureu-vos d'especificar la contrasenya de la clau.

    gpg --gen-key 

  • Recuperar informació clau

    gpg --list-keys -a
    pub   rsa3072 2019-04-24 [SC] [expires: 2021-04-23]
      2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    uid           [ultimate] tttemp <[email protected]>
    sub   rsa3072 2019-04-24 [E] [expires: none]

  • Penjant la nostra clau pública al servidor de claus

    gpg --keyserver keys.gnupg.net --send-key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    gpg: sending key 2D0D1706366FC4AEF79669E24D09C55BBA3FD728 to hkp server keys.gnupg.net

  • Obtenció d'una clau privada

    gpg --export-secret-keys --armor 2D0D1706366FC4AEF79669E24D09C55BBA3FD728
    -----BEGIN PGP PRIVATE KEY BLOCK-----
    lQWGBFzAqp8BDADN41CPwJ/gQwiKEbyA902DKw/WSB1AvZQvV/ZFV77xGeG4K7k5
    ...
    =2Wd2
    -----END PGP PRIVATE KEY BLOCK-----

  • Aneu a la configuració del projecte -> Configuració -> CI / CD -> Variables i deseu la clau privada en una variable GPG_SECRET_KEY
    Configuració de GitLab CI per carregar un projecte java a Maven Central

Al contingut

Configuració de Maven

  • Creeu una clau mestra
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Aneu a la configuració del projecte -> Configuració -> CI / CD -> Variables i deseu en una variable SETTINGS_SECURITY_XML les següents línies:
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Xifrat de la contrasenya des del compte Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Aneu a la configuració del projecte -> Configuració -> CI / CD -> Variables i deseu en una variable SETTINGS_XML les següents línies:
    <settings>  
    <profiles>
        <profile>
            <id>env</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.passphrase>GPG_SECRET_KEY_PASSPHRASE</gpg.passphrase>
            </properties>
        </profile>
    </profiles>
    <servers>
        <server>
            <id>sonatype</id>
            <username>sonatype_username</username>
            <password>{98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}</password>
        </server>
    </servers>
    </settings>

on,
GPG_SECRET_KEY_PASSPHRASE: contrasenya de clau GPG
SONATYPE_USERNAME: inici de sessió al compte de sonatype

Al contingut

Desplega la imatge Docker

  • Creem un Dockerfile bastant senzill per executar tasques en desplegament amb la versió desitjada de Java. A continuació es mostra un exemple per alpí.

    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/

  • Construir un contenidor per al teu projecte

    docker build -t registry.gitlab.com/group/deploy .

  • Autentiquem i carreguem el contenidor al registre.

    docker login -u USER -p PASSWORD registry.gitlab.com
    docker push registry.gitlab.com/group/deploy

Al contingut

GitLab CI

Desplega el projecte

Afegiu el fitxer .gitlab-ci.yml a l'arrel del projecte de desplegament
L'script presenta dues tasques de desplegament mútuament exclusives. Corredor específic o corredor compartit respectivament.

.gitlab-ci.yml

stages:
  - deploy

Specific Runner:
  extends: .java_deploy_template
  # Задача будет выполняться на вашем shell-раннере
  tags:
    - deploy

Shared Runner:
  extends: .java_deploy_template
  # Задача будет выполняться на публичном docker-раннере
  tags:
    - docker
  # Образ из раздела GitLab Runner -> Shared Runner -> Docker
  image: registry.gitlab.com/group/deploy-project:latest
  before_script:
    # Импортируем GPG ключ
    - printf "${GPG_SECRET_KEY}" | gpg --batch --import
    # Сохраняем maven конфигурацию
    - printf "${SETTINGS_SECURITY_XML}" > ~/.m2/settings-security.xml
    - printf "${SETTINGS_XML}" > ~/.m2/settings.xml

.java_deploy_template:
  stage: deploy
  # Задача сработает по триггеру, если передана переменная DEPLOY со значением java
  only:
    variables:
    - $DEPLOY == "java"
  variables:
    # отключаем клонирование текущего проекта
    GIT_STRATEGY: none
  script:
    # Предоставляем возможность хранения пароля в незашифрованном виде
    - git config --global credential.helper store
    # Сохраняем временные креды пользователя gitlab-ci-token
    # Токен работает для всех публичных проектов gitlab.com и для проектов группы
    - echo "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com" >> ~/.git-credentials
    # Полностью чистим текущую директорию
    - rm -rf .* *
    # Клонируем проект который, будем деплоить в Sonatype Nexus
    - git clone ${DEPLOY_CI_REPOSITORY_URL} .
    # Переключаемся на нужный коммит
    - git checkout ${DEPLOY_CI_COMMIT_SHA} -f
    # Если хоть один pom.xml содержит параметр autoReleaseAfterClose валим сборку.
    # В противном случае есть риск залить сырые артефакты в maven central
    - >
      for pom in $(find . -name pom.xml); do
        if [[ $(grep -q autoReleaseAfterClose "$pom" && echo $?) == 0 ]]; then
          echo "File $pom contains prohibited setting: <autoReleaseAfterClose>";
          exit 1;
        fi;
      done
    # Если параметр DEPLOY_CI_COMMIT_TAG пустой, то принудительно ставим SNAPSHOT-версию
    - >
      if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then
        mvn versions:set -DnewVersion=${DEPLOY_CI_COMMIT_TAG}
      else
        VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
        if [[ "${VERSION}" == *-SNAPSHOT ]]; then
          mvn versions:set -DnewVersion=${VERSION}
        else
          mvn versions:set -DnewVersion=${VERSION}-SNAPSHOT
        fi
      fi
    # Запускаем задачу на сборку и деплой артефактов
    - mvn clean deploy -DskipTests=true

Al contingut

Projecte Java

En els projectes java que se suposa que s'han de penjar als dipòsits públics, heu d'afegir 2 passos per descarregar les versions Release i Snapshot.

.gitlab-ci.yml

stages:
  - build
  - test
  - verify
  - deploy

<...>

Release:
  extends: .trigger_deploy
  # Запускать задачу только пo тегу.
  only:
    - tags

Snapshot:
  extends: .trigger_deploy
  # Запускаем задачу на публикацию SNAPSHOT версии вручную
  when: manual
  # Не запускать задачу, если проставлен тег.
  except:
    - tags

.trigger_deploy:
  stage: deploy
  variables:
    # Отключаем клонирование текущего проекта
    GIT_STRATEGY: none
    # Ссылка на триггер deploy-задачи
    URL: "https://gitlab.com/api/v4/projects/<deploy project ID>/trigger/pipeline"
    # Переменные 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:
    # Не использую cURL, так как с флагами --fail --show-error
    # он не выводит тело ответа, если HTTP код 400 и более 
    - wget --content-on-error -qO- ${URL} --post-data ${POST_DATA}

En aquesta solució, vaig anar una mica més enllà i vaig decidir utilitzar una plantilla CI per a projectes java.

Més detalls

Vaig crear un projecte a part gitlab-ci en el qual va col·locar la plantilla CI per a projectes java comú.yml.

comú.yml

stages:
  - build
  - test
  - verify
  - deploy

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

.build_java_project:
  stage: build
  tags:
    - touchbit-shell
  variables:
    SKIP_TEST: "false"
  script:
    - mvn clean
    - mvn package -DskipTests=${SKIP_TEST}
  artifacts:
    when: always
    expire_in: 30 day
    paths:
      - "*/target/reports"

.build_sphinx_doc:
  stage: build
  tags:
    - touchbit-shell
  variables:
    DOCKERFILE: .indirect/docs/Dockerfile
  script:
    - docker build --no-cache -t ${CI_PROJECT_NAME}/doc -f ${DOCKERFILE} .

.junit_module_test_run:
  stage: test
  tags:
    - touchbit-shell
  variables:
    MODULE: ""
  script:
    - cd ${MODULE}
    - mvn test
  artifacts:
    when: always
    expire_in: 30 day
    paths:
      - "*/target/reports"

.junit_test_run:
  stage: test
  tags:
    - touchbit-shell
  script:
    - mvn test
  artifacts:
    when: always
    expire_in: 30 day
    paths:
    - "*/target/reports"

.sonar_review:
  stage: verify
  tags:
    - touchbit-shell
  dependencies: []
  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:
  stage: deploy
  tags:
    - 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:
  extends: .trigger_deploy
  only:
    - tags

.trigger_snapshot_deploy:
  extends: .trigger_deploy
  when: manual
  except:
    - tags

Com a resultat, en els mateixos projectes java, .gitlab-ci.yml sembla molt compacte i no detallat

.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 contingut

configuració pom.xml

Aquest tema es descriu amb gran detall. Googleolplex в Configuració de Maven per signar i penjar artefactes automàticament als repositoris de instantànies i de posada en escena, així que descriuré alguns dels matisos de l'ús de connectors. També descriuré amb quina facilitat i naturalitat podeu utilitzar nexus-staging-maven-pluginsi no voleu o no podeu utilitzar org.sonatype.oss:oss-parent com a pare per al vostre projecte.

maven-install-plugin

Instal·la mòduls al repositori local.
Molt útil per a la verificació local de solucions en altres projectes, així com una suma de control.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-install-plugin</artifactId>
  <executions>
    <execution>
      <id>install-project</id>
      <!-- Если у вас многомодульный проект с деплоем родительского помика -->
      <phase>install</phase>
      <!-- Явно указываем файлы для локальной установки -->
      <configuration>
        <file>target/${project.artifactId}-${project.version}.jar</file>
```target/${project.artifactId}-${project.version}-sources.jar</sources>
        <pomFile>dependency-reduced-pom.xml</pomFile>
        <!-- Принудительное обновление метаданных проекта -->
        <updateReleaseInfo>true</updateReleaseInfo>
        <!-- Контрольные суммы для проверки целостности -->
        <createChecksum>true</createChecksum>
      </configuration>
    </execution>
  </executions>
</plugin>

Al contingut

maven-javadoc-plugin

Generació de javadoc per al projecte.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-javadoc-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>jar</goal>
      </goals>
      <!-- Генерация javadoc должна быть после фазы генерации ресурсов -->
      <phase>prepare-package</phase>
      <configuration>
        <!-- Очень помогает в публичных проектах -->
        <failOnError>true</failOnError>
        <failOnWarnings>true</failOnWarnings>
        <!-- Убирает ошибку поиска документации в target директории -->
        <detectOfflineLinks>false</detectOfflineLinks>
      </configuration>
    </execution>
  </executions>
</plugin>

Si teniu un mòdul que no conté java (per exemple només recursos)
O no voleu generar javadoc en principi, llavors per ajudar maven-jar-plugin

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <executions>
    <execution>
      <id>empty-javadoc-jar</id>
      <phase>generate-resources</phase>
      <goals>
        <goal>jar</goal>
      </goals>
      <configuration>
        <classifier>javadoc</classifier>
        <classesDirectory>${basedir}/javadoc</classesDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

Al contingut

maven-gpg-plugin

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-gpg-plugin</artifactId>
  <executions>
    <execution>
      <id>sign-artifacts</id>
      <!-- Сборка будет падать, если отсутствует GPG ключ -->
      <!-- Подписываем артефакты только на фазе deploy -->
      <phase>deploy</phase>
      <goals>
        <goal>sign</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Al contingut

nexus-staging-maven-plugin

Configuració:

<project>
  <!-- ... -->
  <build>
    <plugins>
      <!-- ... -->
      <plugin>
        <groupId>org.sonatype.plugins</groupId>
        <artifactId>nexus-staging-maven-plugin</artifactId>
      </plugin>
    </plugins>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.sonatype.plugins</groupId>
          <artifactId>nexus-staging-maven-plugin</artifactId>
          <extensions>true</extensions>
          <configuration>
            <serverId>sonatype</serverId>
            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
            <!-- Обновляем метаданные, чтобы пометить артефакт как release -->
            <!-- Не влияет на snapshot версии -->
            <updateReleaseInfo>true</updateReleaseInfo>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <configuration>
            <!-- Отключаем плагин -->
            <skip>true</skip>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
  <distributionManagement>
    <snapshotRepository>
      <id>sonatype</id>
      <name>Nexus Snapshot Repository</name>
      <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    </snapshotRepository>
    <repository>
      <id>sonatype</id>
      <name>Nexus Release Repository</name>
      <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    </repository>
  </distributionManagement>
</project>

Si teniu un projecte de diversos mòduls i no necessiteu carregar un mòdul específic al repositori, haureu d'afegir-lo al pom.xml d'aquest mòdul. nexus-staging-maven-plugin amb bandera skipNexusStagingDeployMojo

<build>
  <plugins>
    <plugin>
      <groupId>org.sonatype.plugins</groupId>
      <artifactId>nexus-staging-maven-plugin</artifactId>
      <configuration>
        <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
      </configuration>
    </plugin>
  </plugins>
</build>

Després de carregar, les versions d'instantànies/alliberament estan disponibles a repositoris de posada en escena

<repositories>
  <repository>
    <id>SonatypeNexus</id>
    <url>https://oss.sonatype.org/content/groups/staging/</url>
    <!-- Не надо указывать флаги snapshot/release для репозитория -->
  </repository>
</repositories>

Més avantatges

  • Una llista molt rica d'objectius per treballar amb el repositori de nexus (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
  • Comprovació automàtica de la descàrrega a Maven Central

Al contingut

Resultat

Publicació d'una versió SNAPSHOT

Quan es construeix un projecte, és possible iniciar manualment una tasca per descarregar la versió SNAPSHOT al nexus

Configuració de GitLab CI per carregar un projecte java a Maven Central

Quan s'inicia aquesta tasca, s'activa la tasca corresponent al projecte de desplegament (exemple).

registre retallat

Running with gitlab-runner 11.10.0 (3001a600)
  on Deploy runner JSKWyxUw
Using Shell executor...
Running on ih1174328.vds.myihor.ru...
Skipping Git repository setup
Skipping Git checkout
Skipping Git submodules setup
$ 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} .
Cloning into 'shields4j'...
$ git checkout ${DEPLOY_CI_COMMIT_SHA}
Note: checking out '850f86aa317194395c5387790da1350e437125a7'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
  git checkout -b new_branch_name
HEAD is now at 850f86a... skip deploy test-core
$ for pom in $(find . -name pom.xml); do # collapsed multi-line command
$ if [[ "${DEPLOY_CI_COMMIT_TAG}" != "" ]]; then # collapsed multi-line command
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 4 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 4 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Shields4J client                                                   [jar]
[INFO] TestNG listener                                                    [jar]
[INFO] 
[INFO] --------------< org.touchbit.shields4j:shields4j-parent >---------------
[INFO] Building Shields4J 1.0.0                                           [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- versions-maven-plugin:2.5:set (default-cli) @ shields4j-parent ---
[INFO] Searching for local aggregator root...
[INFO] Local aggregation root: /home/gitlab-deployer/JSKWyxUw/0/TouchBIT/deploy/shields4j
[INFO] Processing change of org.touchbit.shields4j:shields4j-parent:1.0.0 -> 1.0.0-SNAPSHOT
[INFO] Processing org.touchbit.shields4j:shields4j-parent
[INFO]     Updating project org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:client
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:test-core
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:test-core
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] Processing org.touchbit.shields4j:testng
[INFO]     Updating parent org.touchbit.shields4j:shields4j-parent
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:client
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO]     Updating dependency org.touchbit.shields4j:test-core
[INFO]         from version 1.0.0 to 1.0.0-SNAPSHOT
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[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] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.483 s
[INFO] Finished at: 2019-04-21T02:40:42+03:00
[INFO] ------------------------------------------------------------------------
$ mvn clean deploy -DskipTests=${SKIP_TESTS}
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 4 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 4 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Shields4J                                                          [pom]
[INFO] test-core                                                          [jar]
[INFO] Shields4J client                                                   [jar]
[INFO] TestNG listener                                                    [jar]
[INFO] 
[INFO] --------------< org.touchbit.shields4j:shields4j-parent >---------------
[INFO] Building Shields4J 1.0.0-SNAPSHOT                                  [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
...
DELETED
...
[INFO]  * Bulk deploy of locally gathered snapshot artifacts finished.
[INFO] Remote deploy finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[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] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 47.629 s
[INFO] Finished at: 2019-04-21T02:41:32+03:00
[INFO] ------------------------------------------------------------------------

Com a resultat, es carrega la versió de Nexus 1.0.0-instantània.

Totes les versions d'instantànies es poden eliminar del repositori del lloc oss.sonatype.org sota el teu compte.

Configuració de GitLab CI per carregar un projecte java a Maven Central

Al contingut

Publicació de la versió de llançament

Quan s'estableix l'etiqueta, la tasca corresponent al projecte de desplegament s'activa automàticament per carregar la versió de llançament a nexus (exemple).

Configuració de GitLab CI per carregar un projecte java a Maven Central

La millor part és que l'alliberament tancat s'activa automàticament a Nexus.

[INFO] Performing remote staging...
[INFO] 
[INFO]  * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO]  * Created staging repository with ID "orgtouchbit-1037".
[INFO]  * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1037
[INFO]  * Uploading locally staged artifacts to profile org.touchbit
[INFO]  * Upload of locally staged artifacts finished.
[INFO]  * Closing staging repository with ID "orgtouchbit-1037".
Waiting for operation to complete...
.........
[INFO] Remote staged 1 repositories, finished with success.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... SUCCESS [  9.603 s]
[INFO] test-core .......................................... SUCCESS [  3.419 s]
[INFO] Shields4J client ................................... SUCCESS [  9.793 s]
[INFO] TestNG listener 1.0.0 .............................. SUCCESS [01:23 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:47 min
[INFO] Finished at: 2019-04-21T04:05:46+03:00
[INFO] ------------------------------------------------------------------------

I si alguna cosa va fallar, la tasca fallarà

[INFO] Performing remote staging...
[INFO] 
[INFO]  * Remote staging into staging profile ID "9043b43f77dcc9"
[INFO]  * Created staging repository with ID "orgtouchbit-1038".
[INFO]  * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgtouchbit-1038
[INFO]  * Uploading locally staged artifacts to profile org.touchbit
[INFO]  * Upload of locally staged artifacts finished.
[INFO]  * Closing staging repository with ID "orgtouchbit-1038".
Waiting for operation to complete...
.......
[ERROR] Rule failure while trying to close staging repository with ID "orgtouchbit-1039".
[ERROR] 
[ERROR] Nexus Staging Rules Failure Report
[ERROR] ==================================
[ERROR] 
[ERROR] Repository "orgtouchbit-1039" failures
[ERROR]   Rule "signature-staging" failures
[ERROR]     * No public key: Key with id: (1f42b618d1cbe1b5) was not able to be located on &lt;a href=http://keys.gnupg.net:11371/&gt;http://keys.gnupg.net:11371/&lt;/a&gt;. Upload your public key and try the operation again.
...
[ERROR] Cleaning up local stage directory after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR]  * Deleting context 9043b43f77dcc9.properties
[ERROR] Cleaning up remote stage repositories after a Rule failure during close of staging repositories: [orgtouchbit-1039]
[ERROR]  * Dropping failed staging repository with ID "orgtouchbit-1039" (Rule failure during close of staging repositories: [orgtouchbit-1039]).
[ERROR] Remote staging finished with a failure: Staging rules failure!
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Shields4J 1.0.0 .................................... SUCCESS [  4.073 s]
[INFO] test-core .......................................... SUCCESS [  2.788 s]
[INFO] Shields4J client ................................... SUCCESS [  3.962 s]
[INFO] TestNG listener 1.0.0 .............................. FAILURE [01:07 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

Com a resultat, només ens queda una opció. O suprimiu aquesta versió o publiqueu-la.

Configuració de GitLab CI per carregar un projecte java a Maven Central

Després de l'alliberament, després d'un temps, els artefactes estaran dins Configuració de GitLab CI per carregar un projecte java a Maven Central

fora de tema

Va ser una revelació per a mi que Maven indexa altres dipòsits públics.
Vaig haver de pujar robots.txt perquè indexava el meu antic dipòsit.

Al contingut

Conclusió

El que tenim

  • Un projecte de desplegament independent en el qual podeu implementar diverses tasques de CI per carregar artefactes als repositoris públics per a diversos llenguatges de desenvolupament.
  • El projecte de desplegament està aïllat de les interferències externes i només el poden modificar els usuaris amb els rols de Propietari i Mantenidor.
  • Un corredor específic separat amb una memòria cau "calenta" per executar només tasques de desplegament.
  • Publicació de versions d'instantànies/alliberament en un repositori públic.
  • Comprovació automàtica de la versió de llançament per a la preparació per a la publicació a Maven Central.
  • Protecció contra la publicació automàtica de versions "crues" a maven central.
  • Creeu i publiqueu versions d'instantànies "al clic".
  • Repositori únic per obtenir versions d'instantànies/alliberament.
  • Canalització general per crear / provar / publicar un projecte java.

Configurar GitLab CI no és un tema tan complicat com sembla a primera vista. N'hi ha prou amb configurar CI clau en mà un parell de vegades, i ara estàs lluny de ser un aficionat en aquesta qüestió. A més, la documentació de GitLab és molt redundant. No tinguis por de fer el primer pas. El camí apareix sota els passos de la persona que camina (no recordo qui ho va dir :)

Estaré encantat de fer comentaris.

Al següent article, us mostraré com configurar GitLab CI per executar tasques de prova d'integració de manera competitiva (executant serveis de prova amb docker-compose) si només teniu un shell runner.

Al contingut

Font: www.habr.com

Afegeix comentari