Korištenje Gradle i Github radnji za objavljivanje Java projekta u Sonatype Maven Central Repository

U ovom članku želim detaljno pogledati proces objavljivanja Java artefakta od nule kroz Github Actions do Sonatype Maven Central Repository pomoću Gradle buildera.

Odlučio sam napisati ovaj članak zbog nedostatka normalnog tutorijala na jednom mjestu. Sve informacije trebalo je prikupljati dio po dio iz raznih izvora, štoviše, ne posve svježih. Koga briga, dobrodošao pod kat.

Stvaranje repozitorija u Sonatypeu

Prvi korak je stvaranje repozitorija u Sonatype Maven Central. Za ovo idemo ovdje, registrirajte se i kreirajte novi zadatak, tražeći od nas da stvorimo spremište. Vozimo se u našem GroupId projekt, URL projekta veza projekta i SCM url poveznica na sustav kontrole verzija u kojem se projekt nalazi. GroupId ovdje treba biti u obliku com.example, com.example.domain, com.example.testsupport, a može biti i u obliku veze na vaš github: github.com/vašekorisničkoime -> io.github.vašekorisničkoime. U svakom slučaju, morat ćete potvrditi vlasništvo nad ovom domenom ili profilom. Ako ste naveli github profil, od vas će se tražiti da stvorite javno spremište sa željenim nazivom.

Neko vrijeme nakon potvrde, vaš GroupId će biti kreiran i možemo prijeći na sljedeći korak, Gradle konfiguraciju.

Konfiguriranje Gradle

U vrijeme pisanja nisam pronašao Gradle dodatke koji bi mogli pomoći u objavljivanju artefakta. ovo jedini dodatak koji sam pronašao, međutim, autor ga je odbio dalje podržavati. Stoga sam odlučio sve učiniti sam, jer to nije previše teško učiniti.

Prvo što treba shvatiti su Sonatypeovi zahtjevi za objavljivanje. Oni su sljedeći:

  • Dostupnost izvornih kodova i JavaDoc-a, tj. mora prisustvovati -sources.jar и-javadoc.jar datoteke. Kao što je navedeno u dokumentaciji, ako nije moguće osigurati izvorne kodove ili dokumentaciju, možete izraditi lutku -sources.jar ili -javadoc.jar s jednostavnim README unutra kako biste prošli test.
  • Sve datoteke moraju biti potpisane s GPG/PGPI .asc datoteka koja sadrži potpis mora biti uključena za svaku datoteku.
  • Dostupnost pom datoteka
  • Ispravne vrijednosti groupId, artifactId и version. Verzija može biti proizvoljan niz i ne može završavati s -SNAPSHOT
  • Potrebna prisutnost name, description и url
  • Prisutnost informacija o licenci, programerima i sustavu kontrole verzija

Ovo su osnovna pravila kojih se morate pridržavati prilikom objave. Sve informacije dostupne здесь.

Ove zahtjeve implementiramo u build.gradle datoteka. Prvo, dodajmo sve potrebne informacije o programerima, licencama, sustavu kontrole verzija, a također postavimo url, naziv i opis projekta. Napišimo jednostavnu metodu za ovo:

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

Zatim morate to navesti tijekom generiranog sklopa -sources.jar и-javadoc.jar datoteke. Za ovaj odjeljak java morate dodati sljedeće:

java {
    withJavadocJar()
    withSourcesJar()
}

Prijeđimo na posljednji zahtjev, postavljanje GPG/PGP potpisa. Da biste to učinili, spojite dodatak signing:

plugins {
    id 'signing'
}

I dodajte odjeljak:

signing {
    sign publishing.publications
}

Na kraju, dodajmo odjeljak 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
            }
        }
    }
}

Ovdje sonatypeKorisničkoime и sonatypePassword varijable koje sadrže prijavu i lozinku stvorene tijekom registracije na sonatype.org.

Dakle, finale build.gradle izgledat će ovako:

Potpuni build.gradle kod

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

Želim napomenuti da verziju dobivamo iz varijable okruženja: System.getenv('RELEASE_VERSION'). Izložit ćemo ga tijekom montaže i uzeti iz naziva oznake.

Generiranje PGP ključa

Jedan od Sonatypeovih zahtjeva je da sve datoteke budu potpisane GPG/PGP ključem. Za ovo idemo ovdje i preuzmite uslužni program GnuPG za svoj operativni sustav.

  • Generiramo par ključeva: gpg --gen-key, unesite korisničko ime, e-mail i također postavite lozinku.
  • Saznavši id naš ključ s naredbom: gpg --list-secret-keys --keyid-format short. Id će biti naveden nakon kose crte, na primjer: rsa2048/9B695056
  • Objavljivanje javnog ključa na poslužitelju https://keys.openpgp.org sa naredbom: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Tajni ključ izvozimo na proizvoljno mjesto, trebat će nam u budućnosti: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Postavljanje Github radnji

Prijeđimo na završnu fazu, postavimo izgradnju i automatsko objavljivanje pomoću Github Actions.
Github Actions je značajka koja vam omogućuje automatizaciju tijeka rada implementacijom punog CI/CD ciklusa. Izrada, testiranje i implementacija mogu biti potaknuti raznim događajima: guranje koda, stvaranje izdanja ili problemi. Ova je funkcija potpuno besplatna za javna spremišta.

U ovom odjeljku, pokazat ću vam kako postaviti kod za izgradnju i push i implementirati u repozitorij Sonatype nakon izdavanja, kao i postaviti tajne.

Mi postavljamo tajne

Za automatsku montažu i implementaciju trebamo niz tajnih vrijednosti, kao što je ID ključa, lozinka koju smo unijeli prilikom generiranja ključa, sam PGP ključ i Sonatype prijava/lozinka. Možete ih postaviti u posebnom odjeljku u postavkama repozitorija:

Korištenje Gradle i Github radnji za objavljivanje Java projekta u Sonatype Maven Central Repository

Postavili smo sljedeće varijable:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - prijava / lozinka koju smo unijeli prilikom registracije na Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — ID PGP ključa i lozinka postavljeni tijekom generiranja.

Želim se detaljnije osvrnuti na varijablu GPG_KEY_CONTENTS. Činjenica je da nam je za objavljivanje potreban privatni PGP ključ. Kako bih ga objavio u tajnama, koristio sam instrukcije te dodatno napravio niz akcija.

  • Kriptirajmo naš ključ pomoću gpg-a: gpg --symmetric --cipher-algo AES256 9B695056.gpgunosom lozinke. Treba je smjestiti u varijablu: SECRET_PASSPHRASE
  • Prevedimo primljeni šifrirani ključ u tekstualni oblik koristeći base64: base64 9B695056.gpg.gpg > 9B695056.txt. Sadržaj će biti smješten u varijablu: GPG_KEY_CONTENTS.

Postavljanje izgradnje prilikom guranja koda i stvaranja PR-a

Prvo trebate stvoriti mapu u korijenu vašeg projekta: .github/workflows.

U njemu označite datoteku, npr. gradle-ci-build.yml sa sljedećim sadržajem:

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

Ovaj tijek rada izvršit će se prilikom guranja u grane master, dev и testing, također prilikom kreiranja zahtjeva za povlačenjem.

Odjeljak poslova specificira korake koje treba izvršiti na navedenim događajima. U ovom slučaju gradit ćemo na najnovijoj verziji ubuntua, koristiti Javu 8, a također ćemo koristiti dodatak za Gradle eskatos/gradle-command-action@v1koji će pomoću najnovije verzije alata za izgradnju pokrenuti naredbe navedene u arguments. Varijable secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD ovo su tajne koje smo ranije pitali.

Rezultati izgradnje odrazit će se na kartici Radnje:

Korištenje Gradle i Github radnji za objavljivanje Java projekta u Sonatype Maven Central Repository

Automatska implementacija kada se objavi novo izdanje

Kreirajmo zasebnu datoteku tijeka rada za automatsku implementaciju 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}}

Datoteka je gotovo identična prethodnoj, osim događaja u kojem će se pokrenuti. U ovom slučaju, to je događaj stvaranja oznake s nazivom koji počinje s v.

Prije implementacije moramo izdvojiti PGP ključ iz tajni i smjestiti ga u root projekta, kao i dešifrirati ga. Zatim moramo postaviti posebnu varijablu okoline RELEASE_VERSION na koje se pozivamo gradle.build datoteka. Sve se to radi u odjeljku Prepare to publish. Naš ključ dobivamo iz varijable GPG_KEY_CONTENTS, prevodimo ga u gpg datoteku, a zatim ga dekriptiramo stavljanjem u datoteku secret.gpg.

Zatim se okrećemo posebnoj varijabli GITHUB_REF, iz kojeg možemo dobiti verziju koju smo postavili prilikom izrade oznake. Ova varijabla je relevantna u ovom slučaju. refs/tags/v0.0.2 iz kojeg smo odrezali prvih 11 znakova kako bismo dobili specifičnu verziju. Zatim koristimo standardne Gradle naredbe za objavljivanje: test publish

Provjera rezultata implementacije u Sonatype repozitoriju

Nakon što se izdanje izradi, tijek rada opisan u prethodnom odjeljku trebao bi se pokrenuti. Da biste to učinili, izradite izdanje:

Korištenje Gradle i Github radnji za objavljivanje Java projekta u Sonatype Maven Central Repository

ime oznake mora počinjati s v. Ako nakon klika na Objavi izdanje tijek rada uspješno završi, možemo prijeći na Sonatip Nexus kako bi bili sigurni:

Korištenje Gradle i Github radnji za objavljivanje Java projekta u Sonatype Maven Central Repository

Artefakt se pojavio u repozitoriju Staging. Odmah se pojavljuje u statusu Otvoreno, zatim ga je potrebno ručno prebaciti u status Zatvori pritiskom na odgovarajuću tipku. Nakon provjere jesu li ispunjeni svi zahtjevi, artefakt prelazi u status Zatvori i više nije dostupan za izmjene. U ovom će obliku završiti u MavenCentralu. Ako je sve u redu, možete pritisnuti gumb Pustite, a artefakt će završiti u skladištu Sonatype.

Da bi artefakt ušao u MavenCentral, morate ga zatražiti u zadatku koji smo kreirali na samom početku. Ovo trebate učiniti samo jednom, pa objavljujemo prvi put. U sljedećim vremenima to nije potrebno, sve će se automatski sinkronizirati. Brzo su mi uključili sinkronizaciju, ali je trebalo oko 5 dana da artefakt postane dostupan u MavenCentralu.

To je sve, objavili smo naš artefakt u MavenCentralu.

korisni linkovi

  • Sličan članak, objavi samo putem mavena
  • skele spremište Sonatip
  • Jira Sonatip u kojem treba izraditi zadatak
  • Primjer spremište gdje je sve postavljeno

Izvor: www.habr.com