設置 GitLab CI 將 java 項目上傳到 Maven Central

本文面向需要使用 GitLab 在 sonatype 和/或 Maven 中央存儲庫中快速發布產品的 Java 開發人員。 在這篇文章中,我將討論設置 gitlab-runner、gitlab-ci 和 maven-plugin 來解決這個問題。

先決條件:

  • mvn 和 GPG 密鑰的安全存儲。
  • 安全執行公共 CI 任務。
  • 將工件(發布/快照)上傳到公共存儲庫。
  • 自動檢查發布版本以在 Maven 中心發布。
  • 用於將工件上傳到多個項目的存儲庫的通用解決方案。
  • 簡單易用。

Содержание

一般信息

  • 通過 Sonatype OSS 存儲庫託管服務在 Maven Central 中發布工件的機制的詳細描述已在 本文 用戶 古戈爾普勒克斯,所以我會在正確的地方引用這篇文章。
  • 預註冊 Sonatype JIRA 並啟動票證以打開存儲庫(有關更多詳細信息,請閱讀 部分 在 Sonatype JIRA 上創建票證)。 打開存儲庫後,JIRA 的登錄名/密碼對(以下簡稱 Sonatype 帳戶)將用於將工件上傳到 Sonatype nexus。
  • 接下來非常乾巴巴地描述生成GPG密鑰的過程。 請參閱參考資料部分了解更多詳細信息。 配置 GnuPG 對工件進行簽名
  • 如果您使用Linux控制台生成GPG密鑰(gnupg/gnupg2),那麼您需要安裝 RNG-工具 來產生熵。 否則,密鑰生成可能需要很長時間。
  • 倉儲服務 上市 GPG 密鑰

返回內容

在 GitLab 中設置部署項目

  • 首先,您需要創建並配置一個項目,其中將存儲用於部署工件的管道。 我把我的項目稱為簡單而不復雜 - 部署
  • 創建存儲庫後,您需要限制更改存儲庫的訪問。
    轉到項目 -> 設置 -> 存儲庫 -> 受保護的分支。 我們刪除所有規則並添加帶有通配符 * 的單個規則,該規則僅具有維護者角色的用戶的推送和合併權限。 該規則將適用於該項目及其所屬組的所有用戶。
    設置 GitLab CI 將 java 項目上傳到 Maven Central
  • 如果有多個維護者,那麼最好的解決方案是原則上限制對項目的訪問。
    轉到項目 -> 設置 -> 常規 -> 可見性、項目功能、權限並將項目可見性設置為 私人的.
    我有一個公共訪問的項目,因為我使用自己的 GitLab Runner,並且只有我有權修改存儲庫。 好吧,實際上在公共管道日誌中顯示私人信息並不符合我的利益。
  • 收緊更改存儲庫的規則
    進入項目 -> 設置 -> 存儲庫 -> 推送規則並設置提交者限制,檢查作者是否是 GitLab 用戶標誌。 我還建議設置 提交簽名,並設置拒絕未簽名提交標誌。
  • 接下來您需要配置觸發器來啟動任務
    轉到項目 -> 設置 -> CI / CD -> 管道觸發器並創建一個新的觸發器令牌
    該令牌可以立即添加到一組項目的變量的常規配置中。
    轉到組 -> 設置 -> CI / CD -> 變量並添加變量 DEPLOY_TOKEN 具有觸發令牌的值。

返回內容

GitLab 亞軍

本節介紹使用您自己的(特定)和公共(共享)運行器在部署時運行任務的配置。

特定跑步者

我使用自己的跑步機,因為首先,它方便、快捷、便宜。
對於跑步者,我推薦具有 1 個 CPU、2 GB RAM、20 GB HDD 的 Linux VDS。 發行價約為每年3000₽。

我的跑步者

對於跑步者,我使用了 VDS 4 CPU、4 GB RAM、50 GB SSD。 花費〜11000₽並且從不後悔。
我一共有7台機器。 阿魯巴島 5 個,伊霍爾島 2 個。

所以我們有一個跑步者。 現在我們將對其進行配置。
我們通過 SSH 進入機器並安裝 java、git、maven、gnupg2。

返回內容

安裝 gitlab 運行器

  • 創建一個新組 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 (這可以很簡單,因為本地主機有限制)
    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 帳戶登錄

這樣就完成了跑步者的設置,您可以繼續進行本節 亞搏體育app 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 帳戶登錄

返回內容

部署docker鏡像

  • 我們創建一個相當簡單的 Dockerfile 來使用所需的 Java 版本運行部署任務。 以下是高山的示例。

    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

返回內容

亞搏體育app 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}

在此解決方案中,我更進一步,決定對 Java 項目使用一個 CI 模板。

詳細信息

我創建了一個單獨的項目 gitlab-ci 我在其中放置了 java 項目的 CI 模板 通用.yml.

通用.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 安裝插件

將模塊安裝到本地存儲庫中。
對於其他項目中解決方案的本地驗證以及校驗和非常有用。

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

配置:

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

如果您有一個多模塊項目並且不需要將特定模塊上傳到存儲庫,那麼您需要添加 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

返回內容

發布發布版本

當安裝標籤時,會自動觸發deploy項目中相應的任務將release版本下載到nexus(例子).

設置 GitLab CI 將 java 項目上傳到 Maven Central

最好的部分是關閉釋放會在連接中自動觸發。

[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 任務,以將工件上傳到各種開發語言的公共存儲庫。
  • Deploy 項目與外部干擾隔離,只能由具有 Owner 和Maintainer 角色的用戶進行更改。
  • 具有「熱」快取的單獨特定運行器,僅運行部署任務。
  • 在公共存儲庫中發布快照/發布版本。
  • 自動檢查發布版本是否準備好在 Maven Central 中發布。
  • 防止在 Maven Central 中自動發布「原始」版本。
  • 「點擊」建置和發布快照版本。
  • 用於獲取快照/發布版本的單個存儲庫。
  • 用於構建/測試/發布 java 項目的通用管道。

設定 GitLab CI 並不像乍看那麼複雜。 在交鑰匙的基礎上設置幾次 CI 就足夠了,現在您在這方面遠非業餘。 而且,GitLab 文件非常冗餘。 不要害怕踏出第一步。 路出現在行走的人的腳步下(我不記得是誰說的:)

我會很高興收到反饋。

在下一篇文章中,如果您只有一個 shell 運行程序,我將討論如何配置 GitLab CI 以競爭性地運行帶有集成測試的任務(使用 docker-compose 運行測試中的服務)。

返回內容

來源: www.habr.com

添加評論