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 oddiy o'quv qo'llanmasi yo'qligi sababli ushbu maqolani yozishga qaror qildim. Barcha ma'lumotlar turli manbalardan parcha-parcha to'planishi kerak edi, bundan tashqari, butunlay yangi emas. Kimga g'amxo'rlik qiladi, mushuk ostida xush kelibsiz.

Sonatype-da ombor yaratish

Birinchi qadam Sonatype Maven Central-da omborni yaratishdir. Buning uchun biz boramiz shu yerda, ro'yxatdan o'ting va bizdan ombor yaratishni so'rab, yangi vazifa yarating. Biz mashinamizda haydab chiqamiz GroupId loyiha, Loyiha manzili loyiha havolasi va SCM url loyiha joylashgan versiyani boshqarish tizimiga havola. GroupId bu erda com.example, com.example.domain, com.example.testsupport shaklida bo'lishi kerak va github-ga havola shaklida ham bo'lishi mumkin: github.com/yurusername -> io.github. foydalanuvchi ismingiz. Qanday bo'lmasin, 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 topa olmadim. bu Men topgan yagona plagin, ammo muallif uni qo'llab-quvvatlashdan bosh tortdi. Shuning uchun men hamma narsani o'zim qilishga qaror qildim, chunki buni qilish juda qiyin emas.

Aniqlash kerak bo'lgan birinchi narsa - Sonatype-ning nashrga qo'yadigan talablari. Ular quyidagilar:

  • Manba kodlari va JavaDoc mavjudligi, ya'ni. qatnashishi shart -sources.jar ΠΈ-javadoc.jar fayllar. Hujjatlarda aytilganidek, agar manba kodlari yoki hujjatlarni taqdim etishning iloji bo'lmasa, siz qo'g'irchoq yasashingiz mumkin. -sources.jar yoki -javadoc.jar sinovdan o'tish uchun ichida oddiy README bilan.
  • Barcha fayllar bilan imzolangan bo'lishi kerak GPG/PGPva .asc imzoni o'z ichiga olgan fayl har bir fayl uchun kiritilishi kerak.
  • imkoniyat pom fayl
  • To'g'ri qiymatlar groupId, artifactId ΠΈ version. Versiya ixtiyoriy qator 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'lumot mavjud shu yerda.

Biz ushbu talablarni joriy qilamiz build.gradle fayl. Birinchidan, ishlab chiquvchilar, litsenziyalar, versiyalarni boshqarish tizimi haqida barcha kerakli ma'lumotlarni qo'shamiz, shuningdek, loyihaning url, nomi va tavsifini o'rnatamiz. Buning uchun oddiy usul 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 protected]'
                }
            }
        }
    }
}

Keyinchalik, hosil qilingan yig'ish paytida buni belgilashingiz kerak -sources.jar ΠΈ-javadoc.jar fayllar. Ushbu bo'lim uchun java quyidagilarni qo'shishingiz kerak:

java {
    withJavadocJar()
    withSourcesJar()
}

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

plugins {
    id 'signing'
}

Va bo'lim qo'shing:

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'yxatdan o'tish 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 protected]'
                }
            }
        }
    }
}

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

PGP kalitlarini yaratish

Sonatype talablaridan biri barcha fayllar GPG/PGP kaliti bilan imzolanishidir. Buning uchun biz boramiz shu yerda va operatsion tizimingiz uchun GnuPG yordam dasturini yuklab oling.

  • Biz kalit juftligini yaratamiz: gpg --gen-key, foydalanuvchi nomi, elektron pochta manzilini kiriting, shuningdek parol o'rnating.
  • Biz bilib olamiz id buyruq bilan bizning kalitimiz: gpg --list-secret-keys --keyid-format short. Id qiyshiq chiziqdan keyin ko'rsatiladi, masalan: rsa2048/9B695056
  • Ochiq kalitni serverga nashr qilish https://keys.openpgp.org buyruq bilan: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Biz maxfiy kalitni ixtiyoriy joyga eksport qilamiz, kelajakda bizga kerak bo'ladi: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Github amallarini sozlash

Keling, yakuniy bosqichga o'tamiz, qurilishni o'rnatamiz va Github Actions yordamida avtomatik nashr qilamiz.
Github Actions - bu to'liq CI / CD aylanishini amalga oshirish orqali ish jarayonini avtomatlashtirishga imkon beruvchi xususiyatdir. Yaratish, sinovdan o'tkazish va joylashtirish turli xil hodisalar tufayli yuzaga kelishi mumkin: kodni surish, chiqarishni yaratish yoki muammolar. Bu funksiya umumiy omborlar uchun mutlaqo bepul.

Ushbu bo'limda men sizga kodni yaratish va surish va chiqarilganda Sonatype omboriga joylashtirishni, shuningdek, sirlarni o'rnatishni ko'rsataman.

Biz sirlarni o'rnatdik

Avtomatik yig'ish 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. Siz ularni ombor sozlamalarida maxsus bo'limda o'rnatishingiz 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 parolni yaratish jarayonida o'rnatilgan.

Men GPG_KEY_CONTENTS o'zgaruvchisi haqida batafsilroq to'xtalib o'tmoqchiman. Gap shundaki, nashr qilish uchun bizga shaxsiy PGP kaliti kerak. Uni sirlarga joylashtirish uchun men foydalanardim ko'rsatma va qo'shimcha ravishda bir qator harakatlarni amalga oshirdi.

  • Kalitimizni gpg bilan shifrlaymiz: gpg --symmetric --cipher-algo AES256 9B695056.gpgparolni kiritish orqali. U o'zgaruvchiga joylashtirilishi kerak: SECRET_PASSPHRASE
  • Qabul qilingan shifrlangan kalitni base64 yordamida matn shakliga tarjima qilaylik: base64 9B695056.gpg.gpg > 9B695056.txt. Kontent o'zgaruvchiga joylashtiriladi: GPG_KEY_CONTENTS.

Kodni bosish va PR yaratishda sozlashni yarating

Avval 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 filiallarga bosilganda bajariladi master, dev ΠΈ testing, shuningdek, tortish so'rovlarini yaratishda.

Ishlar bo'limi ko'rsatilgan voqealar bo'yicha bajarilishi kerak bo'lgan qadamlarni belgilaydi. Bunday holda, biz ubuntu-ning so'nggi versiyasini quramiz, Java 8-dan foydalanamiz, shuningdek Gradle plaginidan foydalanamiz. eskatos/gradle-command-action@v1quruvchining so'nggi versiyasidan foydalanib, ko'rsatilgan buyruqlarni bajaradi arguments. O'zgaruvchilar secrets.SONATYPE_USERNAME ΠΈ secrets.SONATYPE_PASSWORD bu biz avval 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

Autodeploy uchun alohida ish jarayoni faylini yarataylik 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, faqat u ishga tushadigan voqea bundan mustasno. Bu holda, bu v bilan boshlanadigan nomli teg yaratish hodisasidir.

Joylashtirishdan oldin biz PGP kalitini sirlardan ajratib olishimiz va uni loyihaning ildiziga joylashtirishimiz, shuningdek shifrini ochishimiz kerak. Keyinchalik, biz maxsus muhit o'zgaruvchisini o'rnatishimiz kerak RELEASE_VERSION biz havola qilamiz gradle.build fayl. Bularning barchasi bo'limda amalga oshiriladi Prepare to publish. Biz kalitni GPG_KEY_CONTENTS o'zgaruvchisidan olamiz, uni gpg fayliga tarjima qilamiz, so'ngra uni faylga qo'yish orqali shifrini hal qilamiz. secret.gpg.

Keyinchalik, biz maxsus o'zgaruvchiga murojaat qilamiz GITHUB_REF, undan biz teg yaratishda o'rnatgan versiyani olishimiz mumkin. Ushbu o'zgaruvchi bu holatda tegishli. refs/tags/v0.0.2 ma'lum bir versiyani olish uchun biz dastlabki 11 ta belgini kesib tashladik. Keyinchalik, nashr qilish uchun standart Gradle buyruqlaridan foydalanamiz: test publish

O'rnatishni tekshirish natijalari Sonatype omborida

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

teg nomi v harfidan boshlanishi kerak. Agar nashr etish tugmasini bosgandan so'ng, ish jarayoni muvaffaqiyatli yakunlansa, biz borishimiz mumkin Nexus sonatipi 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 darhol Ochish holatida paydo bo'ladi, keyin tegishli tugmani bosish orqali uni Yopish holatiga qo'lda o'tkazish kerak. Barcha talablar bajarilganligini tekshirgandan so'ng, artefakt Yopish holatiga o'tadi va endi o'zgartirish uchun mavjud emas. Ushbu shaklda u MavenCentralda tugaydi. Agar hamma narsa yaxshi bo'lsa, tugmani bosishingiz mumkin ozod qilish, va artefakt Sonatype omborida tugaydi.

Artefakt MavenCentral-ga kirishi uchun siz uni boshida biz yaratgan vazifada so'rashingiz kerak. Buni faqat bir marta qilishingiz kerak, shuning uchun biz birinchi marta nashr qilamiz. Keyingi paytlarda bu shart emas, hamma narsa avtomatik ravishda sinxronlashtiriladi. Ular men uchun sinxronizatsiyani tezda yoqdi, ammo artefakt MavenCentral-da mavjud bo'lishi uchun taxminan 5 kun kerak bo'ldi.

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

Foydali havolalar

  • O'xshash maqola, faqat maven orqali nashr eting
  • Staging ombori Sonatip
  • JIRA Vazifa yaratiladigan sonatip
  • misol hammasi o'rnatilgan ombor

Manba: www.habr.com