Používame Gradle a Github Actions na publikovanie Java projektu v Sonatype Maven Central Repository

V tomto článku sa podrobne pozriem na proces publikácie Java artefaktu od nuly cez Github Actions do Sonatype Maven Central Repository s využitím build systému Gradle.

Tento článok som sa rozhodol napísať kvôli absencii kvalitného tutoriálu na jednom mieste. Všetky informácie bolo potrebné poskladať z rôznych zdrojov, pričom nie všetky boli aktuálne. Kto má záujem, vitajte v článku.

Vytvorenie repozitára v Sonatype

Prvým krokom je vytvorenie repozitára v Sonatype Maven Central. Na to ideme sem, registrujeme sa a vytvoríme novú úlohu so žiadosťou o vytvorenie repozitára. Vyplníme svoj GroupId projektu, URL projektu odkaz na projekt a SCM url odkaz na verzionovací systém, v ktorom projekt leží. GroupId tu by mal byť vo formáte com.example, com.example.domain, com.example.testsupport, a tiež môže byť vo forme odkazu na váš github: github.com/yourusername -> io.github.yourusername. Každopádne, budete musieť potvrdiť vlastníctvo daného domény alebo profilu. Ak ste uviedli profil na github, požiadajú vás o vytvorenie verejného repozitára s potrebným názvom.

Po chvíli po potvrdení bude váš GroupId vytvorený a môžeme prejsť na ďalší krok, konfiguráciu Gradle.

Konfigurácia Gradle

V čase písania článku som nenašiel pluginy pre Gradle, ktoré by mohli pomôcť s publikovaním artefaktu. Toto je jediný plugin, ktorý som našiel, avšak autor sa vzdal ďalšej podpory. Preto som sa rozhodol to urobiť všetko sám, našťastie je to celkom jednoduché.

Prvé, čo treba zistiť, sú požiadavky Sonatype na publikáciu. Tie sú nasledovné:

  • Prítomnosť zdrojových kódov a JavaDoc, t.j. musia byť prítomné -sources.jar a-javadoc.jar súbory. Ako uvádza dokumentácia, ak nie je možné poskytnúť zdrojové kódy alebo dokumentáciu, je možné vytvoriť prázdny súbor -sources.jar alebo -javadoc.jar s jednoduchým README vo vnútri, aby ste prešli kontrolou.
  • Všetky súbory musia byť podpísané pomocou GPG/PGP, a .asc súbor obsahujúci podpis musí byť zahrnutý pre každý súbor.
  • Prítomnosť pom súboru
  • Správne hodnoty groupId, artifactId a version. Verzia môže byť ľubovoľný reťazec a nemôže končiť -SNAPSHOT
  • Je potrebné prítomnosť name, description a url
  • Prítomnosť informácií o licencii, vývojároch a verziovacom systéme

Toto sú základné pravidlá, ktoré musia byť dodržiavané pri publikovaní. Kompletné informácie sú dostupné tu.

Implementujeme tieto požiadavky v build.gradle súbore. Na začiatok pridáme všetky potrebné informácie o vývojároch, licenciách, systéme správy verzií a taktiež nastavíme URL, názov a popis projektu. Na tento účel napíšeme jednoduchú metódu:

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

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

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

            description 'Niektorý popis artefaktu'
            name 'Názov artefaktu'
            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 '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'
                }
            }
        }
    }
}

Ďalej je potrebné uviesť, aby sa pri zostavovaní generovali -sources.jar a-javadoc.jar súbory. Na to musíme do sekcie java pridať nasledujúce:

java {
    withJavadocJar()
    withSourcesJar()
}

Prejdeme k poslednej požiadavke, nastaveniu GPG/PGP podpisu. Na to pripojíme plugin signing:

plugins {
    id 'signing'
}

A pridáme sekciu:

signing {
    sign publishing.publications
}

Nakoniec pridáme sekciu 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
            }
        }
    }
}

Tu sonatypeUsername a sonatypePassword premenné, obsahujúce prihlásenie a heslo, vytvorené pri registrácii na sonatype.org.

Takže finálny build.gradle bude vyzerať nasledovne:

Úplný kód build.gradle

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

Chcem upozorniť, že verziu získavame z premennej prostredia: System.getenv('RELEASE_VERSION'). Nastavíme ju pri zostavovaní a vezmeme z názvu tagu.

Generovanie PGP kľúča

Jednou z požiadaviek Sonatype je podpis všetkých súborov pomocou GPG/PGP kľúča. Preto ideme sem a stiahneme nástroj GnuPG pre svoj operačný systém.

  • Vygenerujeme pár kľúčov: gpg --gen-key, zadáme používateľské meno, e-mail a nastavíme heslo.
  • Zistíme id nášho kľúča príkazom: gpg --list-secret-keys --keyid-format short. Id bude uvedené za lomítkom, napríklad: rsa2048/9B695056
  • Zverejníme verejný kľúč na server https://keys.openpgp.org príkazu: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Exportujeme tajný kľúč na náhodné miesto, bude nám potrebný neskôr: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Nastavíme Github Actions

Prejdeme k finálnemu kroku, nastavíme zostavenie a automatickú publikáciu pomocou Github Actions.
Github Actions – funkčnosť, ktorá umožňuje automatizovať pracovný proces a realizovať kompletný cyklus CI/CD. Skladanie, testovanie a nasadenie môžu byť vyvolané rôznymi udalosťami: pushovanie kódu, vytváranie vydania alebo issues. Táto funkcia je úplne zadarmo pre verejné repozitáre.

V tejto časti ukážem, ako nastaviť skladanie, pushovanie kódu a nasadenie do repozitára Sonatype pri vydaní, ako aj nastavenie tajomstiev.

Nastavíme tajomstvá

Pre automatické skladanie a nasadenie budeme potrebovať množstvo tajných hodnôt, ako sú id kľúča, heslo, ktoré sme zadali pri generovaní kľúča, samotný PGP kľúč a prihlasovacie údaje k Sonatype. Môžeme ich nastaviť v špeciálnej sekcii nastavení repozitára:

Používame Gradle a Github Actions na publikovanie Java projektu v Sonatype Maven Central Repository

Nastavujeme nasledujúce premenné:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD — prihlasovacie meno/heslo, ktoré sme zadali pri registrácii v Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — id PGP kľúča a heslo zadané pri generovaní.

Na premennú GPG_KEY_CONTENTS chcem venovať viac pozornosti. Ide o to, že na publikovanie potrebujeme súkromný PGP kľúč. Na to, aby sme ho umiestnili do tajomstiev, som využil inštrukciu a navyše vykonal množstvo krokov.

  • Zašifrujeme náš kľúč pomocou gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, zadaním hesla. To by sme mali umiestniť do premennej: SECRET_PASSPHRASE
  • Prevedieme získaný zašifrovaný kľúč na textovú formu pomocou base64: base64 9B695056.gpg.gpg > 9B695056.txt. Obsah umiestnime do premennej: GPG_KEY_CONTENTS.

Nastavenie skladania pri pushovaní kódu a vytváraní PR

Pre začiatok musíme vytvoriť priečinok v koreňovom adresári vášho projektu: .github/workflows.

V ňom umiestnite súbor, napríklad gradle-ci-build.yml s nasledujúcim obsahom:

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

Tento pracovný proces sa bude vykonávať pri pushovaní do vetiev master, dev a testing, rovnako aj pri vytváraní pull requestov.

V sekcii jobs sú uvedené kroky, ktoré musia byť vykonané pri uvedených udalostiach. V tomto prípade budeme skladanie vykonávať na najnovšej verzii ubuntu, použiť Java 8 a využiť plugin pre Gradle eskatos/gradle-command-action@v1, ktorý pomocou poslednej verzie build systému spustí príkazy uvedené v argumentoch. Premenné secrets.SONATYPE_USERNAME a secrets.SONATYPE_PASSWORD sú to tajomstvá, ktoré sme nastavili skôr.

Výsledky buildovania sa zobrazia na karte Actions:

Používame Gradle a Github Actions na publikovanie Java projektu v Sonatype Maven Central Repository

Automatické nasadenie pri vydaní novej verzie

Na automatické nasadenie vytvoríme samostatný súbor pracovného postupu gradle-ci-publish.yml:

name: publish

on:
  push:
    tags:
      - 'v*'

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

      - name: Pripraviť sa na publikovanie
        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: Publikovať pomocou 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}}

Súbor je takmer identický s predchádzajúcim s výnimkou udalosti, pri ktorej sa spustí. V tomto prípade je to udalosť vytvorenia tagu s názvom, ktorý začína na v.

Pred nasadením musíme vytiahnuť PGP kľúč zo tajomstiev a umiestniť ho do koreňového adresára projektu, ako aj ho dešifrovať. Potom musíme nastaviť špeciálnu premennú prostredia RELEASE_VERSION , na ktorú sa odvolávame v gradle.build súbore. To všetko je vykonané v sekcii Pripraviť sa na publikovanie. Náš kľúč získavame z premennej GPG_KEY_CONTENTS, prevádzame ho do gpg súboru, potom ho dešifrujeme a umiestnime do súboru secret.gpg.

Potom sa odvolávame na špeciálnu premennú GITHUB_REF, z ktorej môžeme získať verziu, ktorú sme nastavili pri vytvorení tagu. Táto premenná má v tomto prípade hodnotu refs/tags/v0.0.2 , z ktorej odstránime prvých 11 znakov, aby sme získali konkrétnu verziu. Potom štandardne používame príkazy Gradle na publikovanie: test publish

Kontrola výsledkov nasadenia do Sonatype repozitára

Po vytvorení vydania by sa mal spustiť pracovný postup opísaný v predchádzajúcej sekcii. Na to vytvárame vydanie:

Používame Gradle a Github Actions na publikovanie Java projektu v Sonatype Maven Central Repository

pričom názov tagu by mal začínať na v. Ak sa po stlačení tlačidla Publikovať vydanie pracovní postup úspešne vykoná, môžeme sa prihlásiť do Sonatype Nexus aby sme sa o tom presvedčili:

Používame Gradle a Github Actions na publikovanie Java projektu v Sonatype Maven Central Repository

Artifact sa objavil v Staging repozitári. Hneď sa zobrazuje v stave Open, potom ho treba ručne preložiť do stavu Close kliknutím na príslušné tlačidlo. Po overení splnenia všetkých požiadaviek artifact prechádza do stavu Close a nie je už dostupný na zmenu. V tejto podobe sa dostane do MavenCentral. Ak je všetko v poriadku, môžete stlačiť tlačidlo Verzia, pričom artifact sa dostane do repozitára Sonatype.

Aby sa artifact dostal do MavenCentral, je potrebné o to požiadať v úlohe, ktorú sme vytvorili na začiatku. Toto je potrebné urobiť iba raz, keďže publikujeme prvýkrát. Pri nasledujúcich prípadoch to nie je potrebné, všetko sa bude synchronizovať automaticky. Synchronizáciu mi zapli rýchlo, ale aby bol artifact dostupný v MavenCentral, trvalo to približne 5 dní.

Na tomto je všetko, publikovali sme náš artifact v MavenCentral.

Užitočné odkazy

  • Podobná článok, len publikácia cez maven
  • Staging repozitár Sonatype
  • Jira Sonatype, v ktorej je potrebné vytvoriť úlohu
  • Príklad repozitára, kde je to všetko nastavené

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster