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 preko Github Actions u Sonatype Maven Central Repository koristeći Gradle builder.

Odlučio sam da napišem ovaj članak zbog nedostatka normalnog tutorijala na jednom mjestu. Sve informacije su se morale prikupljati dio po dio iz raznih izvora, štoviše, ne sasvim svježe. Koga briga, dobrodošao pod mačku.

Kreiranje spremišta u Sonatype

Prvi korak je kreiranje spremišta u Sonatype Maven Central. Za ovo idemo ovdje, registrirajte se i kreirajte novi zadatak, tražeći od nas da kreiramo spremište. Vozimo se u našem GroupId projekat, URL projekta link projekta i SCM url vezu sa sistemom kontrole verzija u kojem se projekat nalazi. GroupId ovdje bi trebalo biti u obliku com.example, com.example.domain, com.example.testsupport, a može biti i u obliku veze na vaš github: github.com/yourusername -> io.github.yourusername. 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 kreirate javno spremište sa željenim imenom.

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

Konfiguriranje Gradlea

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

Prva stvar koju treba shvatiti su Sonatype-ovi zahtjevi za objavljivanje. One su sljedeće:

  • Dostupnost izvornih kodova i JavaDoc-a, tj. mora prisustvovati -sources.jar и-javadoc.jar datoteke. Kao što je navedeno u dokumentaciji, ako nije moguće dati izvorni kod ili dokumentaciju, možete napraviti dummy -sources.jar ili -javadoc.jar sa jednostavnim README unutra da prođe test.
  • Svi fajlovi moraju biti potpisani sa GPG/PGPi .asc datoteka koja sadrži potpis mora biti uključena za svaki fajl.
  • dostupnost pom file
  • Ispravne vrijednosti groupId, artifactId и version. Verzija može biti proizvoljan niz i ne može se završiti sa -SNAPSHOT
  • Potrebno je prisustvo name, description и url
  • Prisutnost informacija o licenci, programerima i sistemu kontrole verzija

Ovo su osnovna pravila kojih se morate pridržavati prilikom objavljivanja. Pune informacije dostupne ovdje.

Ove zahtjeve implementiramo u build.gradle fajl. Prvo, dodajmo sve potrebne informacije o programerima, licencama, sistemu 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 specificirati tokom generiranog sklopa -sources.jar и-javadoc.jar datoteke. Za ovu sekciju java potrebno je dodati sljedeće:

java {
    withJavadocJar()
    withSourcesJar()
}

Pređimo na posljednji zahtjev, postavljanje GPG/PGP potpisa. Da biste to učinili, povežite dodatak signing:

plugins {
    id 'signing'
}

I dodajte odjeljak:

signing {
    sign publishing.publications
}

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

to je sonatypeUsername и sonatypePassword varijable koje sadrže login i lozinku kreirane tokom registracije na sonatype.org.

Dakle finale build.gradle izgledat će ovako:

Cijeli 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 dobijamo iz varijable okruženja: System.getenv('RELEASE_VERSION'). Mi ćemo ga izložiti tokom sastavljanja i uzeti ga iz naziva oznake.

Generisanje PGP ključeva

Jedan od Sonatype-ovih zahtjeva je da svi fajlovi budu potpisani GPG/PGP ključem. Za ovo idemo ovdje i preuzmite GnuPG uslužni program za vaš operativni sistem.

  • Generišemo par ključeva: gpg --gen-key, unesite korisničko ime, e-mail i postavite lozinku.
  • Saznajemo id naš ključ sa naredbom: gpg --list-secret-keys --keyid-format short. Id će biti naveden nakon kose crte, na primjer: rsa2048/9B695056
  • Objavljivanje javnog ključa na serveru https://keys.openpgp.org po komandi: 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 akcija

Prijeđimo na završnu fazu, podesimo izgradnju i automatsko objavljivanje koristeći Github Actions.
Github Actions je funkcija koja vam omogućava da automatizujete tok posla implementacijom punog CI/CD ciklusa. Izgradnju, testiranje i implementaciju mogu pokrenuti različiti događaji: guranje koda, kreiranje izdanja ili problemi. Ova funkcionalnost je potpuno besplatna za javna spremišta.

U ovom odeljku pokazaću vam kako da podesite build i push kod i primenite u skladištu Sonatype po objavljivanju, kao i da podesite tajne.

Mi postavljamo tajne

Za automatsko sklapanje i implementaciju potrebni su nam određeni broj tajnih vrijednosti, kao što su ID ključa, lozinka koju smo unijeli prilikom generiranja ključa, sam PGP ključ i Sonatype login/password. Možete ih postaviti u posebnom dijelu u postavkama spremišta:

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

Postavljamo sljedeće varijable:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - login / lozinka koju smo uneli prilikom registracije na Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — ID PGP ključa i lozinka postavljeni tokom generisanja.

Želim da se zadržim na promenljivoj GPG_KEY_CONTENTS detaljnije. Činjenica je da nam je za objavljivanje potreban privatni PGP ključ. Da bih to objavio u tajnama, koristio sam uputstva i dodatno izvršio niz akcija.

  • Šifrujmo naš ključ sa gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgunosom lozinke. Treba ga staviti 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.

Izgradite postavke prilikom guranja koda i kreiranja PR-a

Prvo morate da kreirate fasciklu u korenu vašeg projekta: .github/workflows.

U njemu označite datoteku, na primjer, 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 radni tok će se izvršiti prilikom guranja na grane master, dev и testing, također prilikom kreiranja zahtjeva za povlačenjem.

Odjeljak poslova specificira korake koji će se izvršiti na navedenim događajima. U ovom slučaju, gradićemo na najnovijoj verziji ubuntu-a, koristiti Javu 8, a takođe ćemo koristiti i dodatak za Gradle eskatos/gradle-command-action@v1koji će, koristeći najnoviju verziju graditelja, pokrenuti naredbe navedene u arguments. Varijable secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD ovo su tajne koje smo ranije pitali.

Rezultati izrade će se odraziti na kartici Akcije:

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 toka posla za autodeploy 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}}

Fajl je skoro identičan prethodnom, osim događaja u kojem će se pokrenuti. U ovom slučaju, ovo je događaj kreiranja oznake s imenom koje počinje s v.

Prije implementacije, moramo izdvojiti PGP ključ iz tajni i smjestiti ga u korijen projekta, kao i dešifrirati ga. Zatim moramo postaviti posebnu varijablu okruženja RELEASE_VERSION na koje se pozivamo gradle.build fajl. Sve ovo se radi u sekciji Prepare to publish. Dobijamo naš ključ iz varijable GPG_KEY_CONTENTS, prevodimo ga u gpg fajl, a zatim ga dešifrujemo tako što ga stavljamo u fajl secret.gpg.

Zatim prelazimo na posebnu varijablu GITHUB_REF, iz koje možemo dobiti verziju koju smo postavili prilikom kreiranja oznake. Ova varijabla je relevantna u ovom slučaju. refs/tags/v0.0.2 od kojih smo odrezali prvih 11 znakova da bismo dobili određenu verziju. Zatim koristimo standardne Gradle komande za objavljivanje: test publish

Provjera rezultata implementacije u skladištu Sonatype

Nakon kreiranja izdanja, tok rada opisan u prethodnom odjeljku bi trebao započeti. Da biste to učinili, kreirajte izdanje:

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

naziv oznake mora početi sa v. Ako se, nakon što kliknete na Objavi izdanje, tok posla uspješno završi, možemo ići na Sonatype Nexus kako bi bili sigurni:

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

Artefakt se pojavio u Staging repozitorijumu. Odmah se pojavljuje u statusu Otvoreno, zatim se mora ručno prebaciti u status Close pritiskom na odgovarajuće dugme. Nakon provjere da su svi zahtjevi ispunjeni, artefakt prelazi u status Close i više nije dostupan za modifikaciju. U ovom obliku će završiti u MavenCentral-u. Ako je sve u redu, možete pritisnuti dugme puštanje, a artefakt će završiti u skladištu Sonatype.

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

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

korisni linkovi

  • Slično članak, objaviti samo preko mavena
  • Staging spremište Sonatype
  • Jira Sonatype u kojem se kreira zadatak
  • Primjer: spremište u kojem je sve postavljeno

izvor: www.habr.com