Java loyihasini Sonatype Maven markaziy omboriga nashr qilish uchun Gradle va Github amallaridan foydalanish

Ushbu maqolada men Gradle quruvchisi yordamida Github Actions orqali Sonatype Maven markaziy omboriga Java artefaktini noldan nashr qilish jarayonini batafsil ko'rib chiqmoqchiman.

Bir joyda tegishli o'quv qo'llanmasi yo'qligi sababli ushbu maqolani yozishga qaror qildim. Barcha ma'lumotlar turli manbalardan to'planishi kerak edi, ularning ba'zilari to'liq yangilanmagan. Agar qiziqsangiz, quyida xush kelibsiz.

Sonatype-da ombor yaratish

Birinchi qadam Sonatype Maven Central-da omborni yaratishdir. Buni amalga oshirish uchun quyidagi manzilga o'ting shu yerda, ro'yxatdan o'ting va biz uchun ombor yaratishni so'rab, yangi vazifa yarating. O'zingizni kiriting GroupId loyiha, Loyiha manzili loyihaga havola va SCM url loyiha joylashgan versiyani boshqarish tizimiga havola. GroupId Bu com.example, com.example.domain, com.example.testsupport kabi bo'lishi kerak va GitHub-ga havola ham bo'lishi mumkin: github.com/yurusername -> io.github. foydalanuvchi ismingiz. Ikkala holatda ham ushbu domen yoki profilga egalik huquqini tasdiqlashingiz kerak bo‘ladi. Agar siz GitHub profilini ko'rsatgan bo'lsangiz, sizdan kerakli nom bilan umumiy ombor yaratishingiz so'raladi.

Tasdiqlashdan bir muncha vaqt o'tgach, sizning GroupIdingiz yaratiladi va biz keyingi bosqichga, Gradle konfiguratsiyasiga o'tishimiz mumkin.

Gradle sozlanmoqda

Yozish paytida men artefaktni nashr etishda yordam beradigan Gradle plaginlarini topmadim. bu Men topgan yagona plagin, lekin muallif uni qo'llab-quvvatlashdan bosh tortdi. Shuning uchun men buni o'zim qilishga qaror qildim, xayriyatki, bu unchalik qiyin emas edi.

Siz bilishingiz kerak bo'lgan birinchi narsa - Sonatype nashriyotiga qo'yiladigan talablar. Ular quyidagicha:

  • Manba kodlari va JavaDoc mavjudligi, ya'ni mavjud bo'lishi kerak -sources.jar и-javadoc.jar fayllar. Hujjatlarda aytilganidek, agar manba kodini yoki hujjatlarni taqdim etishning iloji bo'lmasa, qo'g'irchoq yaratilishi mumkin. -sources.jar yoki -javadoc.jar sinovdan o'tish uchun ichida oddiy README bilan.
  • Barcha fayllar bilan imzolangan bo'lishi kerak GPG/PGPva .asc Har bir fayl uchun imzoni o'z ichiga olgan fayl kiritilishi kerak.
  • Mavjudlik pom fayl
  • To'g'ri qiymatlar groupId, artifactId и versionVersiya har qanday satr bo'lishi mumkin va u bilan tugamaydi -SNAPSHOT
  • Mavjudlik talab qilinadi name, description и url
  • Litsenziya, ishlab chiquvchilar va versiyalarni boshqarish tizimi haqida ma'lumotlarning mavjudligi

Nashr qilishda rioya qilish kerak bo'lgan asosiy qoidalar bu. To'liq ma'lumotlar mavjud. shu yerda.

Biz ushbu talablarni amalga oshiramiz build.gradle fayl. Birinchidan, ishlab chiquvchilar, litsenziya, versiya boshqaruv tizimi haqida barcha kerakli ma'lumotlarni qo'shamiz, shuningdek, loyiha URL manzilini, nomini va tavsifini o'rnatamiz. Buning uchun oddiy usulni yozamiz:

def customizePom(pom) {
    pom.withXml {
        def root = asNode()

        root.dependencies.removeAll { dep ->
            dep.scope == "test"
        }

        root.children().last() + {
            resolveStrategy = DELEGATE_FIRST

            description 'Some description of artifact'
            name 'Artifct name'
            url 'https://github.com/login/projectname'
            organization {
                name 'com.github.login'
                url 'https://github.com/login'
            }
            issueManagement {
                system 'GitHub'
                url 'https://github.com/login/projectname/issues'
            }
            licenses {
                license {
                    name 'The Apache License, Version 2.0'
                    url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                }
            }
            scm {
                url 'https://github.com/login/projectname'
                connection 'scm:https://github.com/login/projectname.git'
                developerConnection 'scm:git://github.com/login/projectname.git'
            }
            developers {
                developer {
                    id 'dev'
                    name 'DevName'
                    email 'email@dev.ru'
                }
            }
        }
    }
}

Keyinchalik, yig'ish paytida quyidagilar yaratilishi kerakligini belgilashingiz kerak: -sources.jar и-javadoc.jar fayllar. Buning uchun bo'limga o'ting java quyidagilarni qo'shishingiz kerak:

java {
    withJavadocJar()
    withSourcesJar()
}

Keling, oxirgi talabga o'tamiz: GPG/PGP imzosini o'rnatish. Buning uchun plaginni yoqamiz. signing:

plugins {
    id 'signing'
}

Va bo'limni qo'shamiz:

signing {
    sign publishing.publications
}

Va nihoyat, bo'limni qo'shamiz publishing:

publishing {
    publications {
        mavenJava(MavenPublication) {
            customizePom(pom)
            groupId group
            artifactId archivesBaseName
            version version

            from components.java
        }
    }
    repositories {
        maven {
            url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            credentials {
                username sonatypeUsername
                password sonatypePassword
            }
        }
    }
}

u sonatypeFoydalanuvchi nomi и sonatypeParol ro'yxatga olish paytida yaratilgan login va parolni o'z ichiga olgan o'zgaruvchilar sonatype.org.

Shunday qilib, final build.gradle quyidagicha ko'rinadi:

To'liq build.gradle kodi

plugins {
    id 'java'
    id 'maven-publish'
    id 'signing'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
    withJavadocJar()
    withSourcesJar()
}

group 'io.github.githublogin'
archivesBaseName = 'projectname'
version = System.getenv('RELEASE_VERSION') ?: "0.0.1"

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
}

test {
    useJUnitPlatform()
}

jar {
    from sourceSets.main.output
    from sourceSets.main.allJava
}

signing {
    sign publishing.publications
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            customizePom(pom)
            groupId group
            artifactId archivesBaseName
            version version

            from components.java
        }
    }
    repositories {
        maven {
            url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            credentials {
                username sonatypeUsername
                password sonatypePassword
            }
        }
    }
}

def customizePom(pom) {
    pom.withXml {
        def root = asNode()

        root.dependencies.removeAll { dep ->
            dep.scope == "test"
        }

        root.children().last() + {
            resolveStrategy = DELEGATE_FIRST

            description 'Some description of artifact'
            name 'Artifct name'
            url 'https://github.com/login/projectname'
            organization {
                name 'com.github.login'
                url 'https://github.com/githublogin'
            }
            issueManagement {
                system 'GitHub'
                url 'https://github.com/githublogin/projectname/issues'
            }
            licenses {
                license {
                    name 'The Apache License, Version 2.0'
                    url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                }
            }
            scm {
                url 'https://github.com/githublogin/projectname'
                connection 'scm:https://github.com/githublogin/projectname.git'
                developerConnection 'scm:git://github.com/githublogin/projectname.git'
            }
            developers {
                developer {
                    id 'dev'
                    name 'DevName'
                    email 'email@dev.ru'
                }
            }
        }
    }
}

Shuni ta'kidlashni istardimki, biz versiyani muhit o'zgaruvchisidan olamiz: System.getenv('RELEASE_VERSION')Biz uni yig'ish paytida o'rnatamiz va teg nomidan olamiz.

PGP kalitlarini yaratish

Sonatype talablaridan biri barcha fayllarni GPG/PGP kaliti bilan imzolashdir. Buni amalga oshirish uchun quyidagi manzilga o'ting shu yerda va operatsion tizimingiz uchun GnuPG yordam dasturini yuklab oling.

  • Kalitlar juftligini yarating: gpg --gen-key, foydalanuvchi nomingizni, elektron pochtangizni kiriting va parol o'rnating.
  • Keling, bilib olaylik id buyruq bilan bizning kalitimiz: gpg --list-secret-keys --keyid-format shortID chiziqdan keyin ko'rsatiladi, masalan: rsa2048/9B695056
  • Ochiq kalitni serverga e'lon qiling https://keys.openpgp.org buyruq bilan: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Biz maxfiy kalitni istalgan joyga eksport qilamiz; bizga keyinroq kerak bo'ladi: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Github amallarini sozlash

Yakuniy bosqichga o'tamiz: Github Actions yordamida qurish va avtomatik nashr qilishni sozlash.
Github Actions - bu to'liq CI/CD siklini amalga oshirib, ish jarayonini avtomatlashtiradigan xususiyatdir. Qurilishlar, testlar va tarqatishlar turli xil hodisalar, masalan, kodni surish, relizlar yaratish yoki muammolar tufayli yuzaga kelishi mumkin. Bu xususiyat ommaviy omborlar uchun mutlaqo bepul.

Ushbu bo'limda men sizga relizni chiqarishda Sonatype omboriga kod yaratish, surish va joylashtirishni qanday sozlashni, shuningdek, sirlarni qanday sozlashni ko'rsataman.

Biz sirlarni so'raymiz

Avtomatik qurish va joylashtirish uchun bizga kalit identifikatori, kalitni yaratishda biz kiritgan parol, PGP kalitining o'zi va Sonatype login/parol kabi bir qator maxfiy qiymatlar kerak bo'ladi. Ularni ombor sozlamalarining maxsus bo'limida sozlash mumkin:

Java loyihasini Sonatype Maven markaziy omboriga nashr qilish uchun Gradle va Github amallaridan foydalanish

Biz quyidagi o'zgaruvchilarni o'rnatamiz:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD — Sonatype bilan ro'yxatdan o'tishda biz kiritgan login/parol
  • SIGNING_KEYID/SIGNING_PASSWORD — PGP kalit identifikatori va parol yaratish jarayonida o'rnatiladi.

Men GPG_KEY_CONTENTS o'zgaruvchisi haqida batafsil ma'lumot bermoqchiman. Gap shundaki, nashr qilish uchun bizga shaxsiy PGP kaliti kerak. Uni yashirincha joylashtirish uchun men foydalanardim ko'rsatma va qo'shimcha ravishda bir qator harakatlarni amalga oshirdi.

  • Gpg yordamida kalitimizni shifrlaymiz: gpg --symmetric --cipher-algo AES256 9B695056.gpg, parolni kiritish. U o'zgaruvchiga joylashtirilishi kerak: SECRET_PASSPHRASE
  • Qabul qilingan shifrlangan kalitni base64 yordamida matn shakliga aylantiramiz: base64 9B695056.gpg.gpg > 9B695056.txtTarkibni o'zgaruvchiga joylashtiramiz: GPG_KEY_CONTENTS.

Kodni bosish va PR yaratishda qurilishni sozlash

Birinchidan, loyihangizning ildizida papka yaratishingiz kerak: .github/workflows.

Unda faylni belgilang, masalan, gradle-ci-build.yml quyidagi tarkib bilan:

name: build

on:
  push:
    branches:
      - master
      - dev
      - testing
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 8
        uses: actions/setup-java@v1
        with:
          java-version: 8

      - name: Build with Gradle
        uses: eskatos/gradle-command-action@v1
        with:
          gradle-version: current
          arguments: build -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}

Ushbu ish jarayoni filialga bosilganda amalga oshiriladi. master, dev и testing, shuningdek, tortish so'rovlarini yaratishda.

Ishlar bo'limi ko'rsatilgan voqealar asosida bajarilishi kerak bo'lgan qadamlarni belgilaydi. Bunday holda, biz Java 8 va Gradle plaginidan foydalangan holda Ubuntu-ning so'nggi versiyasini quramiz. eskatos/gradle-command-action@v1, bu kollektorning so'nggi versiyasidan foydalanib, da ko'rsatilgan buyruqlarni bajaradi arguments. O'zgaruvchilar secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD Bu biz ilgari so'ragan sirlar.

Qurilish natijalari "Amallar" yorlig'ida aks etadi:

Java loyihasini Sonatype Maven markaziy omboriga nashr qilish uchun Gradle va Github amallaridan foydalanish

Yangi versiya chiqqanda avtomatik joylashtirish

Autodeployment uchun biz alohida ish jarayoni faylini yaratamiz gradle-ci-publish.yml:

name: publish

on:
  push:
    tags:
      - 'v*'

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 8
        uses: actions/setup-java@v1
        with:
          java-version: 8

      - name: Prepare to publish
        run: |
          echo '${{secrets.GPG_KEY_CONTENTS}}' | base64 -d > publish_key.gpg
          gpg --quiet --batch --yes --decrypt --passphrase="${{secrets.SECRET_PASSPHRASE}}" 
          --output secret.gpg publish_key.gpg
          echo "::set-env name=RELEASE_VERSION::${GITHUB_REF:11}"

      - name: Publish with Gradle
        uses: eskatos/gradle-command-action@v1
        with:
          gradle-version: current
          arguments: test publish -Psigning.secretKeyRingFile=secret.gpg -Psigning.keyId=${{secrets.SIGNING_KEYID}} -Psigning.password=${{secrets.SIGNING_PASSWORD}} -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}

Fayl avvalgisi bilan deyarli bir xil, uni ishga tushiradigan hodisa bundan mustasno. Bu holda, bu v harfidan boshlanadigan nomli teg yaratishdir.

Joylashtirishdan oldin biz PGP kalitini sirlardan ajratib olishimiz va uni loyiha ildiziga joylashtirishimiz, shuningdek shifrini ochishimiz kerak. Keyinchalik, biz maxsus muhit o'zgaruvchisini o'rnatishimiz kerak. RELEASE_VERSION biz unga murojaat qilamiz gradle.build fayl. Bularning barchasi bo'limda amalga oshiriladi Prepare to publishBiz kalitni GPG_KEY_CONTENTS o'zgaruvchisidan olamiz, uni gpg fayliga tarjima qilamiz, so'ng shifrini hal qilamiz va faylga joylashtiramiz. secret.gpg.

Keyinchalik biz maxsus o'zgaruvchiga murojaat qilamiz GITHUB_REF, undan biz teg yaratishda ko'rsatgan versiyani olishimiz mumkin. Bu holda bu o'zgaruvchi qiymatga ega refs/tags/v0.0.2 Muayyan versiyani olish uchun biz dastlabki 11 ta belgini kesib tashlaymiz. Keyinchalik, nashr qilish uchun standart Gradle buyruqlaridan foydalanamiz: test publish

O'rnatishni tekshirish natijasida Sonatype ombori paydo bo'ladi

Chiqarish yaratilgandan so'ng, oldingi bo'limda tasvirlangan ish jarayoni boshlanishi kerak. Buning uchun reliz yarating:

Java loyihasini Sonatype Maven markaziy omboriga nashr qilish uchun Gradle va Github amallaridan foydalanish

bu holda teg nomi v harfi bilan boshlanishi kerak. Agar nashr etish tugmasini bosgandan so'ng ish jarayoni muvaffaqiyatli bo'lsa, biz o'tishimiz mumkin Nexus sonatipi Bunga ishonch hosil qilish uchun:

Java loyihasini Sonatype Maven markaziy omboriga nashr qilish uchun Gradle va Github amallaridan foydalanish

Artefakt Staging omborida paydo bo'ldi. U dastlab Ochish holatida paydo bo'ladi, lekin keyin tegishli tugmani bosish orqali Yopish holatiga qo'lda o'zgartirilishi kerak. Barcha talablar tekshirilgandan so'ng, artefakt Yopish holatiga o'tkaziladi va endi o'zgartirish uchun mavjud emas. Bu shtatda MavenCentral-ga qo'shiladi. Agar hamma narsa yaxshi bo'lsa, tugmani bosishingiz mumkin. ozod qilish, va artefakt Sonatype omboriga qo'shiladi.

MavenCentral-ga artefaktni olish uchun siz uni boshida yaratgan vazifamizda so'rashingiz kerak. Buni faqat bir marta qilishingiz kerak, chunki biz buni birinchi marta shunday nashr qilamiz. Keyingi paytlarda buni qilish shart emas; hamma narsa avtomatik ravishda sinxronlanadi. Ular men uchun sinxronlashni tezda yoqdi, ammo artefakt MavenCentral-da mavjud bo'lishi uchun taxminan besh kun kerak bo'ldi.

Mana, biz o'z artefaktimizni MavenCentral-da nashr qildik.

Foydali havolalar

  • O'xshash maqola, faqat maven orqali nashr etiladi
  • Staging ombori Sonatip
  • JIRA Sonatype, unda siz vazifa yaratishingiz kerak
  • misol hammasi sozlangan ombor

Manba: www.habr.com