Настройване на GitLab CI за качване на java проект в maven central

Тази статия е предназначена за разработчици на Java, които трябва бързо да публикуват своите продукти в централните хранилища на sonatype и/или maven с помощта на GitLab. В тази статия ще говоря за настройването на gitlab-runner, gitlab-ci и maven-plugin за решаване на този проблем.

Предпоставки:

  • Безопасно съхранение на mvn и GPG ключове.
  • Сигурно изпълнение на публични CI задачи.
  • Качване на артефакти (версия/моментна снимка) в публични хранилища.
  • Автоматична проверка на версиите за публикуване в maven central.
  • Общо решение за качване на артефакти в хранилище за множество проекти.
  • Простота и лекота на използване.

Съдържание

Обща информация

  • Подробно описание на механизма за публикуване на артефакти в Maven Central чрез Sonatype OSS Repository Hosting Service вече е описано в тази статия потребител гуголплекс, така че ще препращам към тази статия на правилните места.
  • Предварителна регистрация на Sonatype JIRA и стартирайте билет за отваряне на хранилището (за повече подробности прочетете раздела Създайте билет за Sonatype JIRA). След отваряне на хранилището двойката потребителско име/парола на JIRA (наричана по-долу акаунт на Sonatype) ще се използва за качване на артефакти в Nexus на Sonatype.
  • Освен това процесът на генериране на GPG ключ е описан много сухо. Вижте раздела за повече подробности. Конфигуриране на GnuPG за подписване на артефакти
  • Ако използвате Linux конзолата за генериране на GPG ключ (gnupg/gnupg2), тогава трябва да инсталирате RNG инструменти за генериране на ентропия. В противен случай генерирането на ключ може да отнеме много време.
  • Услуги за съхранение публичен GPG ключове

Към съдържанието

Настройване на проект за внедряване в GitLab

  • На първо място, трябва да създадете и конфигурирате проект, в който тръбопроводът ще се съхранява за внедряване на артефакти. Нарекох проекта си просто и неусложнено - разположи
  • След като създадете хранилището, трябва да ограничите достъпа, за да промените хранилището.
    Отидете на проекта -> Настройки -> Хранилище -> Защитени клонове. Ние изтриваме всички правила и добавяме едно правило със заместващ знак * с право на натискане и сливане само за потребители с ролята на поддържащи. Това правило ще работи за всички потребители както на този проект, така и на групата, към която този проект принадлежи.
    Настройване на GitLab CI за качване на java проект в maven central
  • Ако има няколко поддържащи, тогава най-доброто решение би било да се ограничи достъпът до проекта по принцип.
    Отидете на проекта -> Настройки -> Общи -> Видимост, функции на проекта, разрешения и задайте Видимост на проекта на частен.
    Имам проект в публичен достъп, тъй като използвам собствения си GitLab Runner и само аз имам достъп да променям хранилището. Е, всъщност не е в мой интерес да показвам лична информация в публичните регистрационни файлове на тръбопровода.
  • Затягане на правилата за промяна на хранилището
    Отидете на проекта -> Настройки -> Хранилище -> Push Rules и задайте флаговете Committer restriction, Проверете дали авторът е потребител на GitLab. Аз също препоръчвам настройка ангажирам подписванеи задайте флага за отхвърляне на неподписани ангажименти.
  • След това трябва да конфигурирате тригер за изпълнение на задачи
    Отидете на проект -> Настройки -> CI / CD -> Задействания на тръбопровода и създайте нов тригер-токен
    Този токен може незабавно да бъде добавен към общата конфигурация на променливите за група проекти.
    Отидете в групата -> Настройки -> CI / CD -> Променливи и добавете променлива DEPLOY_TOKEN с trigger-token в стойността.

Към съдържанието

GitLab Runner

Този раздел описва конфигурацията за изпълнение на задачи при разгръщане с помощта на родния (специфичен) и публичен (споделен) инструмент за изпълнение.

Конкретен бегач

Използвам собствени бегачи, защото преди всичко е удобно, бързо, евтино.
За runner препоръчвам Linux VDS с 1 CPU, 2 GB RAM, 20 GB HDD. Емисионна цена ~ 3000₽ на година.

Моят бегач

За бегача взех VDS 4 CPU, 4 GB RAM, 50 GB SSD. Струва ~11000₽ и никога не съжалявам.
Имам общо 7 машини. 5 на аруба и 2 на ihor.

И така, имаме бегач. Сега ще го настроим.
Отиваме до машината през SSH и инсталираме java, git, maven, gnupg2.

Към съдържанието

Инсталиране на gitlab runner

  • Създайте нова група runner
    sudo groupadd runner
  • Създайте директория за кеша на maven и задайте групови права runner
    Можете да пропуснете тази стъпка, ако не планирате да стартирате няколко бегача на една и съща машина.

    mkdir -p /usr/cache/.m2/repository
    chown -R :runner /usr/cache
    chmod -R 770 /usr/cache
  • Създайте потребител gitlab-deployer и добавете към групата runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • Добавяне към файла /etc/ssh/sshd_config следващ ред
    AllowUsers root@* [email protected]
  • Рестартирайте sshd
    systemctl restart sshd
  • Задайте парола за потребителя gitlab-deployer (може да е просто, тъй като има ограничение за localhost)
    passwd gitlab-deployer
  • Инсталирайте 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
  • Отидете на gitlab.com -> deploy-project -> Settings -> CI/CD -> Runners -> Specific Runners и копирайте токена за регистрация

екран

Настройване на GitLab CI за качване на java проект в maven central

  • Регистриране на бегача
    gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml

процес

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!

  • Проверете дали бегачът е регистриран. Отидете на gitlab.com -> deploy-project -> Settings -> CI/CD -> Runners -> Specific Runners -> Runners, активирани за този проект

екран

Настройване на GitLab CI за качване на java проект в maven central

  • Добавете отделно услуга /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
  • Стартираме услугата.
    systemctl enable gitlab-deployer.service
    systemctl start gitlab-deployer.service
    systemctl status gitlab-deployer.service
  • Проверете дали бегачът работи.

Пример

Настройване на GitLab CI за качване на java проект в maven central

Към съдържанието

Генериране на GPG ключ

  • От същата машина преминаваме през ssh под потребителя gitlab-deployer (това е важно за генерирането на GPG ключ)

    ssh [email protected]

  • Ние генерираме ключ, като отговаряме на въпроси. Използвах собственото си име и имейл.
    Не забравяйте да посочите паролата за ключа. Артефактите ще бъдат подписвани с този ключ.

    gpg --gen-key 

  • проверите

    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

  • Качване на нашия публичен ключ на сървъра за ключове

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

Към съдържанието

Настройка на Maven

  • Отиваме под потребителя gitlab-deployer
    su gitlab-deployer 
  • Създайте директория maven хранилище и връзка с кеша (не правете грешка)
    Тази стъпка може да се пропусне, ако не планирате да стартирате няколко бегача на една и съща машина.

    mkdir -p ~/.m2/repository
    ln -s /usr/cache/.m2/repository /home/gitlab-deployer/.m2/repository
  • Създайте главен ключ
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Създайте файл ~/.m2/settings-security.xml
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Шифроване на паролата от акаунта на Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Създайте файл ~/.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>

където,
GPG_SECRET_KEY_PASSPHRASE - Парола за GPG ключ
SONATYPE_USERNAME - влизане в акаунта на sonatype

Това завършва настройката на бегача, можете да продължите към раздела GitLab CI

Към съдържанието

Споделен бегач

Генериране на GPG ключ

  • На първо място, трябва да създадете GPG ключ. За да направите това, инсталирайте gnupg.

    yum install -y gnupg

  • Ние генерираме ключ, като отговаряме на въпроси. Използвах собственото си име и имейл. Не забравяйте да посочите паролата за ключа.

    gpg --gen-key 

  • Извлечете ключова информация

    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]

  • Качване на нашия публичен ключ на сървъра за ключове

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

  • Получаване на частен ключ

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

  • Отидете на настройките на проекта -> Настройки -> CI / CD -> Променливи и запазете личния ключ в променлива GPG_SECRET_KEY
    Настройване на GitLab CI за качване на java проект в maven central

Към съдържанието

Настройка на Maven

  • Създайте главен ключ
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Отидете на настройките на проекта -> Настройки -> CI / CD -> Променливи и запишете в променлива SETTINGS_SECURITY_XML следните редове:
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Шифроване на паролата от акаунта на Sonatype
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Отидете на настройките на проекта -> Настройки -> CI / CD -> Променливи и запишете в променлива 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>

където,
GPG_SECRET_KEY_PASSPHRASE - Парола за GPG ключ
SONATYPE_USERNAME - влизане в акаунта на sonatype

Към съдържанието

Разположете докер изображение

  • Ние създаваме доста прост Dockerfile за изпълнение на задачи при внедряване с желаната версия на Java. По-долу е даден пример за 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/

  • Изграждане на контейнер за вашия проект

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

  • Ние удостоверяваме и зареждаме контейнера в системния регистър.

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

Към съдържанието

GitLab CI

Разположете проект

Добавете файла .gitlab-ci.yml към корена на проекта за разгръщане
Скриптът представя две взаимно изключващи се задачи за внедряване. Конкретен бегач или съответно споделен бегач.

.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

Към съдържанието

Java проект

В java проекти, които трябва да бъдат качени в публични хранилища, трябва да добавите 2 стъпки за изтегляне на версиите Release и 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}

В това решение отидох малко по-далеч и реших да използвам един CI шаблон за java проекти.

Повече подробности

Създадох отделен проект gitlab-ci в който той постави CI шаблона за java проекти common.yml.

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

В резултат на това в самите java проекти .gitlab-ci.yml изглежда много компактен и не многословен

.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

Към съдържанието

pom.xml конфигурация

Тази тема е описана много подробно. гуголплекс в Настройване на maven за автоматично подписване и качване на артефакти в хранилища за моментни снимки и етапи, така че ще опиша някои от нюансите на използването на плъгини. Ще опиша също колко лесно и естествено можете да използвате nexus-staging-maven-pluginако не искате или не можете да използвате org.sonatype.oss:oss-parent като родител за вашия проект.

maven-install-plugin

Инсталира модули в локалното хранилище.
Много полезно за локална проверка на решения в други проекти, както и за контролна сума.

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

Към съдържанието

maven-javadoc-плъгин

Генериране на javadoc за проекта.

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

Ако имате модул, който не съдържа java (например само ресурси)
Или не искате да генерирате javadoc по принцип, тогава да помогнете 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>

Към съдържанието

maven-gpg-плъгин

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

Към съдържанието

nexus-staging-maven-plugin

Конфигурация:

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

Ако имате многомодулен проект и не е необходимо да качвате конкретен модул в хранилището, тогава трябва да добавите към pom.xml на този модул nexus-staging-maven-plugin със знаме skipNexusStagingDeployMojo

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

След качване на моментна снимка/издание версиите са налични в сценични хранилища

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

Още плюсове

  • Много богат списък от цели за работа с хранилището на nexus (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
  • Автоматична проверка за изтегляне за изтегляне в maven central

Към съдържанието

Резултат

Публикуване на МОМЕНТНА СНИМКА

Когато създавате проект, е възможно ръчно да стартирате задача за изтегляне на версията SNAPSHOT на nexus

Настройване на GitLab CI за качване на java проект в maven central

Когато тази задача се стартира, се задейства съответната задача в проекта за внедряване (пример).

изрязан труп

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] ------------------------------------------------------------------------

В резултат на това се зарежда версията на nexus 1.0.0-МОМЕНТАЛНА СНИМКА.

Всички версии на моментни снимки могат да бъдат премахнати от хранилището на сайта oss.sonatype.org под вашия акаунт.

Настройване на GitLab CI за качване на java проект в maven central

Към съдържанието

Публикуване на версията за освобождаване

Когато маркерът е зададен, съответната задача в проекта за внедряване се задейства автоматично, за да качи версията на изданието в nexus (пример).

Настройване на GitLab CI за качване на java проект в maven central

Най-добрата част е, че затвореното освобождаване автоматично се задейства в 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] ------------------------------------------------------------------------

И ако нещо се обърка, тогава задачата ще се провали

[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] ------------------------------------------------------------------------

В резултат на това ни остава само един избор. Или изтрийте тази версия или публикувайте.

Настройване на GitLab CI за качване на java проект в maven central

След освобождаването, след известно време, артефактите ще бъдат вътре Настройване на GitLab CI за качване на java проект в maven central

извън темата

За мен беше откровение, че maven индексира други публични хранилища.
Трябваше да кача robots.txt, защото индексира старото ми хранилище.

Към съдържанието

Заключение

Това, което имаме

  • Отделен проект за внедряване, в който можете да реализирате няколко CI задачи за качване на артефакти в публични хранилища за различни езици за разработка.
  • Проектът за внедряване е изолиран от външна намеса и може да бъде модифициран само от потребители с роли на собственик и поддържащ.
  • Отделен специфичен Runner с „горещ“ кеш за изпълнение само на задачи за разгръщане.
  • Публикуване на моментни снимки/релиз версии в публично хранилище.
  • Автоматична проверка на версията на изданието за готовност за публикуване в maven central.
  • Защита срещу автоматично публикуване на „сурови“ версии в maven central.
  • Създавайте и публикувайте версии на моментни снимки „при щракване“.
  • Единично хранилище за получаване на моментни снимки/релиз версии.
  • Обща линия за изграждане / тестване / публикуване на java проект.

Настройката на GitLab CI не е толкова сложна тема, колкото изглежда на пръв поглед. Достатъчно е да настроите CI до ключ няколко пъти и сега далеч не сте аматьор по този въпрос. Освен това документацията на GitLab е много излишна. Не се страхувайте да направите първата крачка. Пътят се появява под стъпките на човека, който върви (не помня кой го каза :)

Ще се радвам на обратна връзка.

В следващата статия ще ви покажа как да настроите GitLab CI за конкурентно изпълнение на тестови задачи за интеграция (извършване на тестови услуги с docker-compose), ако имате само един shell runner.

Към съдържанието

Източник: www.habr.com

Добавяне на нов коментар