Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Denne artikkelen er ment for java-utviklere som har behov for å raskt publisere produktene sine i sonatype og/eller maven sentrale repositories ved hjelp av GitLab. I denne artikkelen vil jeg snakke om å sette opp gitlab-runner, gitlab-ci og maven-plugin for å løse dette problemet.

Forutsetninger:

  • Sikker lagring av mvn- og GPG-nøkler.
  • Sikker utførelse av offentlige CI-oppgaver.
  • Opplasting av artefakter (utgivelse/øyeblikksbilde) til offentlige depoter.
  • Automatisk kontroll av utgivelsesversjoner for publisering i maven sentral.
  • En generell løsning for å laste opp artefakter til et depot for flere prosjekter.
  • Enkelhet og brukervennlighet.

Innhold

Generell informasjon

  • En detaljert beskrivelse av mekanismen for publisering av artefakter i Maven Central via Sonatype OSS Repository Hosting Service er allerede beskrevet i denne artikkelen bruker googolplex, så jeg vil referere til denne artikkelen på de riktige stedene.
  • Forhåndsregistrer deg for Sonatype JIRA og åpne en billett for å åpne depotet (les delen for flere detaljer Lag en billett på Sonatype JIRA). Etter å ha åpnet depotet, vil påloggings-/passordparet fra JIRA (heretter referert til som Sonatype-kontoen) brukes til å laste opp artefakter til Sonatype-nexus.
  • Deretter beskrives prosessen med å generere en GPG-nøkkel veldig tørt. Se avsnittet for flere detaljer Konfigurerer GnuPG til å signere artefakter
  • Hvis du bruker Linux-konsollen til å generere en GPG-nøkkel (gnupg/gnupg2), må du installere RNG-verktøy å generere entropi. Ellers kan nøkkelgenerering ta svært lang tid.
  • Lagringstjenester offentlig GPG-nøkler

Til innholdet

Sette opp et distribusjonsprosjekt i GitLab

  • Først av alt må du opprette og konfigurere et prosjekt der rørledningen vil bli lagret for distribusjon av artefakter. Jeg kalte prosjektet mitt enkelt og ukomplisert - utplassere
  • Etter å ha opprettet depotet, må du begrense tilgangen for å endre depotet.
    Gå til prosjekt -> Innstillinger -> Depot -> Beskyttede grener. Vi sletter alle regler og legger til en enkelt regel med Wildcard * med rett til å push og flette kun for brukere med Maintainers-rollen. Denne regelen vil fungere for alle brukere av både dette prosjektet og gruppen som dette prosjektet tilhører.
    Sette opp GitLab CI for å laste opp et java-prosjekt til maven central
  • Hvis det er flere vedlikeholdere, vil den beste løsningen være å begrense tilgangen til prosjektet i prinsippet.
    Gå til prosjekt -> Innstillinger -> Generelt -> Synlighet, prosjektfunksjoner, tillatelser og sett Prosjektsynlighet til Privat.
    Jeg har et offentlig tilgjengelig prosjekt, siden jeg bruker min egen GitLab Runner og bare jeg har tilgang til å endre depotet. Vel, faktisk er det ikke i min interesse å vise privat informasjon i offentlige rørledningslogger.
  • Innstramming av reglene for endring av depot
    Gå til prosjektet -> Innstillinger -> Repository -> Push Rules og sett Committer-begrensningen, Sjekk om forfatteren er et GitLab-brukerflagg. Jeg anbefaler også å sette opp forplikte signatur, og sett flagget Reject unsigned commits.
  • Deretter må du konfigurere en utløser for å starte oppgaver
    Gå til prosjekt -> Innstillinger -> CI / CD -> Pipeline-utløsere og opprett et nytt trigger-token
    Dette tokenet kan umiddelbart legges til den generelle konfigurasjonen av variabler for en gruppe prosjekter.
    Gå til gruppe -> Innstillinger -> CI / CD -> Variabler og legg til en variabel DEPLOY_TOKEN med trigger-token i verdi.

Til innholdet

GitLab Runner

Denne delen beskriver konfigurasjonen for å kjøre oppgaver ved distribusjon med din egen (spesifikke) og offentlige (delte) løper.

Spesifikk løper

Jeg bruker mine egne løpere fordi det først og fremst er praktisk, raskt og billig.
For en løper anbefaler jeg en Linux VDS med 1 CPU, 2 GB RAM, 20 GB HDD. Emisjonskursen er ~3000 ₽ per år.

Min løper

For løperen tok jeg VDS 4 CPU, 4 GB RAM, 50 GB SSD. Kostet ~11000 XNUMX ₽ og angret aldri.
Jeg har totalt 7 maskiner. 5 på aruba og 2 på ihor.

Så vi har en løper. Nå skal vi konfigurere det.
Vi går til maskinen via SSH og installerer java, git, maven, gnupg2.

Til innholdet

Installerer gitlab runner

  • Opprett en ny gruppe runner
    sudo groupadd runner
  • Opprett en katalog for maven-cachen og tildel gruppetillatelser runner
    Du kan hoppe over dette punktet hvis du ikke planlegger å kjøre flere løpere på en maskin.

    mkdir -p /usr/cache/.m2/repository
    chown -R :runner /usr/cache
    chmod -R 770 /usr/cache
  • Opprett en bruker gitlab-deployer og legge til i gruppen runner
    useradd -m -d /home/gitlab-deployer gitlab-deployer
    usermod -a -G runner gitlab-deployer
  • Legg til i fil /etc/ssh/sshd_config neste linje
    AllowUsers root@* [email protected]
  • Start på nytt sshd
    systemctl restart sshd
  • Sette et passord for brukeren gitlab-deployer (kan være enkelt, siden det er en begrensning for lokalvert)
    passwd gitlab-deployer
  • Installer 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
  • Gå til nettstedet gitlab.com -> deploy-project -> Innstillinger -> CI/CD -> Runners -> Specific Runners og kopier registreringstokenet

Skjerm

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

  • Registrere en løper
    gitlab-runner register --config /etc/gitlab-runner/gitlab-deployer-config.toml

prosessen

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!

  • Vi sjekker at løperen er påmeldt. Gå til nettstedet gitlab.com -> deploy-project -> Innstillinger -> CI/CD -> Løpere -> Spesifikke løpere -> Løpere aktivert for dette prosjektet

Skjerm

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

  • legge separat tjeneste /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
  • La oss starte tjenesten.
    systemctl enable gitlab-deployer.service
    systemctl start gitlab-deployer.service
    systemctl status gitlab-deployer.service
  • Vi sjekker at løperen løper.

Eksempel

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Til innholdet

Genererer GPG-nøkler

  • Fra samme maskin logger vi inn via ssh under brukeren gitlab-deployer (dette er viktig for å generere GPG-nøkkelen)

    ssh [email protected]

  • Vi genererer en nøkkel ved å svare på spørsmål. Jeg brukte mitt eget navn og e-post.
    Sørg for å spesifisere passordet for nøkkelen. Artefakter vil bli signert med denne nøkkelen.

    gpg --gen-key 

  • Sjekker

    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

  • Laster opp vår offentlige nøkkel til nøkkelserveren

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

Til innholdet

Setter opp Maven

  • Logg inn som bruker gitlab-deployer
    su gitlab-deployer 
  • Lag en maven-katalog Repository og lenke til cachen (ikke ta feil)
    Du kan hoppe over dette punktet hvis du ikke planlegger å kjøre flere løpere på en maskin.

    mkdir -p ~/.m2/repository
    ln -s /usr/cache/.m2/repository /home/gitlab-deployer/.m2/repository
  • Lag en hovednøkkel
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Opprett en fil ~/.m2/settings-security.xml
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Krypterer passordet for Sonatype-kontoen
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Opprett en fil ~/.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>

hvor,
GPG_SECRET_KEY_PASSPHRASE - passord for GPG-nøkkelen
SONATYPE_USERNAME — sonatype-kontopålogging

Dette fullfører oppsettet av løperen, du kan gå videre til delen GitLab CI

Til innholdet

Delt løper

Genererer GPG-nøkler

  • Først av alt må du lage en GPG-nøkkel. For å gjøre dette, installer gnupg.

    yum install -y gnupg

  • Vi genererer en nøkkel ved å svare på spørsmål. Jeg brukte mitt eget navn og e-post. Sørg for å spesifisere passordet for nøkkelen.

    gpg --gen-key 

  • Viser informasjon på nøkkelen

    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]

  • Laster opp vår offentlige nøkkel til nøkkelserveren

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

  • Vi får den private nøkkelen

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

  • Gå til prosjektinnstillinger -> Innstillinger -> CI / CD -> Variabler og lagre den private nøkkelen i en variabel GPG_SECRET_KEY
    Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Til innholdet

Setter opp Maven

  • Lag en hovednøkkel
    mvn --encrypt-master-password password
    {hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}
  • Gå til prosjektinnstillinger -> Innstillinger -> CI / CD -> Variabler og lagre i en variabel SETTINGS_SECURITY_XML følgende linjer:
    <settingsSecurity>
    <master>{hnkle5BJ9HUHUMP+CXfGBl8dScfFci/mpsur/73tR2I=}</master>
    </settingsSecurity>
  • Krypterer passordet for Sonatype-kontoen
    mvn --encrypt-password SONATYPE_PASSWORD
    {98Wv5+u+Tn0HX2z5G/kR4R8Z0WBgcDBgi7d12S/un+SCU7uxzaZGGmJ8Cu9pAZ2J}
  • Gå til prosjektinnstillinger -> Innstillinger -> CI / CD -> Variabler og lagre i en variabel SETTINGS_XML følgende linjer:
    <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>

hvor,
GPG_SECRET_KEY_PASSPHRASE - passord for GPG-nøkkelen
SONATYPE_USERNAME — sonatype-kontopålogging

Til innholdet

Implementer docker-bilde

  • Vi lager en ganske enkel Dockerfile for å kjøre distribusjonsoppgaver med den nødvendige versjonen av Java. Nedenfor er et eksempel for alpint.

    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/

  • Sette sammen en beholder for prosjektet ditt

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

  • Vi autentiserer og laster beholderen inn i registeret.

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

Til innholdet

GitLab CI

Distribuer prosjekt

Legg til .gitlab-ci.yml-filen til roten av distribusjonsprosjektet
Skriptet presenterer to gjensidig utelukkende distribusjonsoppgaver. henholdsvis spesifikk løper eller delt løper.

.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

Til innholdet

Java-prosjekt

I java-prosjekter som er ment å lastes opp til offentlige depoter, må du legge til 2 trinn for å laste ned utgivelses- og øyeblikksbildeversjonene.

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

I denne løsningen gikk jeg litt lenger og bestemte meg for å bruke én CI-mal for java-prosjekter.

Flere detaljer

Jeg har laget et eget prosjekt gitlab-ci der jeg plasserte en CI-mal for java-prosjekter vanlig.yml.

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

Som et resultat, i selve java-prosjektene, ser .gitlab-ci.yml veldig kompakt ut og ikke utførlig

.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

Til innholdet

Pom.xml-konfigurasjon

Dette emnet er beskrevet i stor detalj. googolplex в Konfigurere Maven til automatisk å signere og laste opp artefakter til øyeblikksbilder og iscenesettelser, så jeg vil beskrive noen av nyansene ved bruk av plugins. Jeg vil også beskrive hvor enkelt og avslappet du kan bruke nexus-staging-maven-pluginhvis du ikke vil eller kan bruke org.sonatype.oss:oss-parent som forelder for prosjektet ditt.

maven-install-plugin

Installerer moduler i det lokale depotet.
Meget nyttig for lokal verifisering av løsninger i andre prosjekter, samt en sjekksum.

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

Til innholdet

maven-javadoc-plugin

Genererer javadoc for prosjektet.

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

Hvis du har en modul som ikke inneholder java (for eksempel bare ressurser)
Eller du vil i prinsippet ikke generere javadoc, så hjelp 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>

Til innholdet

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>

Til innholdet

nexus-staging-maven-plugin

Konfigurasjon:

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

Hvis du har et flermodulprosjekt og du ikke trenger å laste opp en spesifikk modul til depotet, må du legge til nexus-staging-maven-plugin med flagg skipNexusStagingDeployMojo

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

Etter nedlasting er snapshot-/utgivelsesversjoner tilgjengelig i iscenesettelse av depoter

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

Flere plusser

  • En veldig rik liste over mål for å jobbe med nexus-depotet (mvn help:describe -Dplugin=org.sonatype.plugins:nexus-staging-maven-plugin).
  • Automatisk utgivelsessjekk for opplasting til maven central

Til innholdet

Resultat

Publiserer SNAPSHOT-versjon

Når du bygger et prosjekt, er det mulig å starte en oppgave manuelt for å laste ned SNAPSHOT-versjonen til nexus

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Når denne oppgaven startes, utløses den tilsvarende oppgaven i distribusjonsprosjektet (eksempel).

Trimmet stokk

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

Som et resultat blir versjonen lastet inn i nexus 1.0.0-SNAPSHOT.

Alle snapshot-versjoner kan slettes fra depotet på nettstedet oss.sonatype.org under kontoen din.

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Til innholdet

Publiserer en utgivelsesversjon

Når en tag er installert, utløses den tilsvarende oppgaven i distribusjonsprosjektet automatisk for å laste ned utgivelsesversjonen til nexus (eksempel).

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Det beste er at lukkefrigjøring utløses automatisk i 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] ------------------------------------------------------------------------

Og hvis noe går galt, vil oppgaven definitivt mislykkes

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

Som et resultat står vi igjen med bare ett valg. Enten slett denne versjonen eller publiser den.

Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

Etter utgivelsen, etter en tid vil gjenstandene være inne Sette opp GitLab CI for å laste opp et java-prosjekt til maven central

offtopic

Det var en oppdagelse for meg at Maven indekserer andre offentlige depoter.
Jeg måtte legge til robots.txt fordi det indekserte det gamle depotet mitt.

Til innholdet

Konklusjon

Hva vi har

  • Et eget distribusjonsprosjekt der du kan implementere flere CI-oppgaver for å laste opp artefakter til offentlige depoter for ulike utviklingsspråk.
  • Deploy-prosjektet er isolert fra forstyrrelser utenfor og kan bare endres av brukere med rollene eier og vedlikeholder.
  • En separat spesifikk løper med en "hot" cache for å kjøre bare distribusjonsoppgaver.
  • Publisering av øyeblikksbilde/utgivelsesversjoner i et offentlig depot.
  • Automatisk sjekk av utgivelsesversjonen for beredskap for publisering i maven sentral.
  • Beskyttelse mot automatisk publisering av "rå" versjoner i maven central.
  • Bygg og publiser øyeblikksbildeversjoner "ved klikk".
  • Et enkelt depot for å skaffe øyeblikksbilde/utgivelsesversjoner.
  • Generell pipeline for å bygge/teste/publisere et java-prosjekt.

Å sette opp GitLab CI er ikke et så komplisert emne som det ser ut ved første øyekast. Det er nok å sette opp CI på nøkkelferdig basis et par ganger, og nå er du langt fra en amatør i denne saken. Dessuten er GitLab-dokumentasjon veldig overflødig. Ikke vær redd for å ta det første skrittet. Veien dukker opp under trinnene til personen som går (jeg husker ikke hvem som sa det :)

Jeg vil gjerne motta tilbakemeldinger.

I den neste artikkelen skal jeg snakke om hvordan du konfigurerer GitLab CI til å kjøre oppgaver med integrasjonstester konkurransedyktig (kjøre tjenestene som testes ved hjelp av docker-compose) hvis du bare har en shell-løper.

Til innholdet

Kilde: www.habr.com

Legg til en kommentar