Použitie akcií Gradle a Github na publikovanie projektu Java v centrálnom úložisku Sonatype Maven

V tomto článku sa chcem podrobne pozrieť na proces publikovania artefaktu Java od nuly cez akcie Github do centrálneho úložiska Sonatype Maven pomocou nástroja Gradle builder.

Tento článok som sa rozhodol napísať kvôli nedostatku normálneho tutoriálu na jednom mieste. Všetky informácie bolo treba zbierať po kúskoch z rôznych zdrojov, navyše nie úplne čerstvé. Koho to zaujíma, vitaj pod kat.

Vytvorenie úložiska v Sonatype

Prvým krokom je vytvorenie úložiska v Sonatype Maven Central. Pre toto ideme tu, zaregistrujte sa a vytvorte novú úlohu a požiadajte nás o vytvorenie úložiska. Jazdíme v našom GroupId projekt, Adresa URL projektu odkaz na projekt a Adresa URL SCM odkaz na systém správy verzií, v ktorom sa projekt nachádza. GroupId tu by malo byť vo forme com.example, com.example.domain, com.example.testsupport a môže byť aj vo forme odkazu na váš github: github.com/vaše používateľské meno -> io.github.vaše používateľské meno. V každom prípade budete musieť overiť vlastníctvo tejto domény alebo profilu. Ak ste zadali profil github, zobrazí sa výzva na vytvorenie verejného úložiska s požadovaným názvom.

Po určitom čase po potvrdení sa vytvorí vaše GroupId a môžeme prejsť k ďalšiemu kroku, konfigurácii Gradle.

Konfigurácia Gradle

V čase písania článku som nenašiel Gradle pluginy, ktoré by mohli pomôcť s publikovaním artefaktu. To jediný plugin, ktorý som našiel, ho však autor odmietol ďalej podporovať. Preto som sa rozhodol urobiť všetko sám, pretože to nie je príliš ťažké.

Prvá vec, ktorú treba zistiť, sú požiadavky Sonatype na publikovanie. Sú to tieto:

  • Dostupnosť zdrojových kódov a JavaDoc, tzn. sa musí zúčastniť -sources.jar и-javadoc.jar súbory. Ako je uvedené v dokumentácii, ak nie je možné poskytnúť zdrojové kódy alebo dokumentáciu, môžete si vytvoriť figurínu -sources.jar alebo -javadoc.jar s jednoduchým README vo vnútri, aby ste prešli testom.
  • Všetky súbory musia byť podpísané GPG/PGPA .asc súbor obsahujúci podpis musí byť súčasťou každého súboru.
  • dostupnosť pom súbor
  • Správne hodnoty groupId, artifactId и version. Verzia môže byť ľubovoľný reťazec a nemôže končiť -SNAPSHOT
  • Vyžaduje sa prítomnosť name, description и url
  • Prítomnosť informácií o licencii, vývojároch a systéme riadenia verzií

Toto sú základné pravidlá, ktoré treba pri zverejňovaní dodržiavať. Úplné informácie k dispozícii tu.

Tieto požiadavky implementujeme v build.gradle súbor. Najprv doplníme všetky potrebné informácie o vývojároch, licenciách, systéme riadenia verzií a tiež si nastavíme url, názov a popis projektu. Napíšeme si na to 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 '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]'
                }
            }
        }
    }
}

Ďalej to musíte zadať počas generovania zostavy -sources.jar и-javadoc.jar súbory. Pre túto sekciu java musíte pridať nasledovné:

java {
    withJavadocJar()
    withSourcesJar()
}

Prejdime k poslednej požiadavke, a to k nastaveniu GPG/PGP podpisu. Ak to chcete urobiť, pripojte doplnok signing:

plugins {
    id 'signing'
}

A pridajte sekciu:

signing {
    sign publishing.publications
}

Na záver 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 sonatypePoužívateľské meno и sonatypePassword premenné obsahujúce prihlasovacie meno a heslo vytvorené pri registrácii na sonatype.org.

Teda finále build.gradle bude vyzerať takto:

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

Chcem poznamenať, že verziu získame z premennej prostredia: System.getenv('RELEASE_VERSION'). Pri montáži ho vystavíme a preberieme z názvu tagu.

Generovanie kľúča PGP

Jednou z požiadaviek Sonatype je, aby všetky súbory boli podpísané kľúčom GPG/PGP. Pre toto ideme tu a stiahnite si pomôcku GnuPG pre váš operačný systém.

  • Vygenerujeme kľúčový pár: gpg --gen-key, zadajte používateľské meno, e-mail a tiež nastavte heslo.
  • Zisťujeme id náš kľúč s príkazom: gpg --list-secret-keys --keyid-format short. Id bude uvedené za lomkou, napríklad: rsa2048/9B695056
  • Publikovanie verejného kľúča na server https://keys.openpgp.org príkazom: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Tajný kľúč exportujeme na ľubovoľné miesto, budeme ho potrebovať v budúcnosti: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Nastavenie akcií Github

Prejdime do poslednej fázy, nastavme zostavenie a automatické publikovanie pomocou akcií Github.
Github Actions je funkcia, ktorá vám umožňuje automatizovať pracovný tok implementáciou celého cyklu CI / CD. Zostavovanie, testovanie a nasadzovanie môžu byť spustené rôznymi udalosťami: vloženie kódu, vytvorenie vydania alebo problémy. Táto funkcia je pre verejné úložiská úplne zadarmo.

V tejto časti vám ukážem, ako nastaviť zostavovací a doručovací kód a nasadiť ho do úložiska Sonatype pri vydaní, ako aj nastaviť tajomstvá.

Stanovili sme tajomstvá

Na automatické zostavenie a nasadenie potrebujeme množstvo tajných hodnôt, ako je ID kľúča, heslo, ktoré sme zadali pri generovaní kľúča, samotný kľúč PGP a prihlasovacie meno/heslo Sonatype. Môžete ich nastaviť v špeciálnej sekcii v nastaveniach úložiska:

Použitie akcií Gradle a Github na publikovanie projektu Java v centrálnom úložisku Sonatype Maven

Nastavili sme nasledujúce premenné:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - prihlasovacie meno / heslo, ktoré sme zadali pri registrácii v Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — ID kľúča PGP a heslo nastavené počas generovania.

Chcem sa podrobnejšie zaoberať premennou GPG_KEY_CONTENTS. Faktom je, že na zverejnenie potrebujeme súkromný kľúč PGP. Aby som to zapísal do tajničiek, použil som inštrukcia a navyše vykonala množstvo akcií.

  • Poďme zašifrovať náš kľúč pomocou gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgzadaním hesla. Mal by byť umiestnený v premennej: SECRET_PASSPHRASE
  • Preložme prijatý šifrovaný kľúč do textovej podoby pomocou base64: base64 9B695056.gpg.gpg > 9B695056.txt. Obsah bude umiestnený do premennej: GPG_KEY_CONTENTS.

Vytvorte nastavenie pri tlačení kódu a vytváraní PR

Najprv musíte vytvoriť priečinok v koreňovom adresári vášho projektu: .github/workflows.

V ňom označte súbor, napr. 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ý postup sa vykoná pri tlačení do pobočiek master, dev и testing, aj pri vytváraní požiadaviek na stiahnutie.

Sekcia úloh špecifikuje kroky, ktoré sa majú vykonať pri zadaných udalostiach. V tomto prípade budeme stavať na najnovšej verzii ubuntu, používať Java 8 a tiež používať plugin pre Gradle eskatos/gradle-command-action@v1ktorý pomocou najnovšej verzie zostavovača spustí príkazy špecifikované v arguments. Premenné secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD toto sú tajomstvá, na ktoré sme sa pýtali predtým.

Výsledky zostavenia sa prejavia na karte Akcie:

Použitie akcií Gradle a Github na publikovanie projektu Java v centrálnom úložisku Sonatype Maven

Automatické nasadenie pri vydaní nového vydania

Vytvorme samostatný súbor pracovného postupu pre automatické nasadenie 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}}

Súbor je takmer identický s predchádzajúcim, až na udalosť, pri ktorej sa spustí. V tomto prípade ide o udalosť vytvorenia značky s názvom začínajúcim na v.

Pred nasadením musíme extrahovať kľúč PGP z tajomstiev a umiestniť ho do koreňového adresára projektu, ako aj dešifrovať. Ďalej musíme nastaviť špeciálnu premennú prostredia RELEASE_VERSION na ktoré sa odvolávame gradle.build súbor. To všetko sa robí v sekcii Prepare to publish. Náš kľúč získame z premennej GPG_KEY_CONTENTS, preložíme ho do súboru gpg a potom ho dešifrujeme vložením do súboru secret.gpg.

Ďalej sa obrátime na špeciálnu premennú GITHUB_REF, z ktorého môžeme získať verziu, ktorú sme nastavili pri vytváraní značky. Táto premenná je v tomto prípade relevantná. refs/tags/v0.0.2 z ktorého sme odrezali prvých 11 znakov, aby sme získali konkrétnu verziu. Ďalej na publikovanie používame štandardné príkazy Gradle: test publish

Kontrola výsledkov nasadenia v úložisku Sonatype

Po vytvorení vydania by sa mal spustiť pracovný postup popísaný v predchádzajúcej časti. Ak to chcete urobiť, vytvorte vydanie:

Použitie akcií Gradle a Github na publikovanie projektu Java v centrálnom úložisku Sonatype Maven

názov značky musí začínať na v. Ak sa po kliknutí na Publikovať vydanie pracovný postup úspešne dokončí, môžeme prejsť na Sonatype Nexus aby sa ubezpečil:

Použitie akcií Gradle a Github na publikovanie projektu Java v centrálnom úložisku Sonatype Maven

Artefakt sa objavil v úložisku Staging. Okamžite sa objaví v stave Otvorené, následne ho treba manuálne preniesť do stavu Zatvoriť stlačením príslušného tlačidla. Po skontrolovaní, či sú splnené všetky požiadavky, artefakt prejde do stavu Close a už nie je k dispozícii na úpravu. V tejto podobe skončí v MavenCentral. Ak je všetko v poriadku, môžete stlačiť tlačidlo Verziaa artefakt skončí v úložisku Sonatype.

Aby sa artefakt dostal do MavenCentral, musíte oň požiadať v úlohe, ktorú sme vytvorili na úplnom začiatku. Stačí to urobiť len raz, preto publikujeme prvýkrát. V ďalších časoch to už nie je potrebné, všetko sa zosynchronizuje automaticky. Rýchlo mi zapli synchronizáciu, ale trvalo asi 5 dní, kým bol artefakt dostupný v MavenCentral.

To je všetko, náš artefakt sme zverejnili v MavenCentral.

Užitočné odkazy

  • Podobný článok, publikovať iba cez maven
  • Predstavovať Úložisko Sonatyp
  • Jira Sonatyp, v ktorom vytvoríte úlohu
  • Príklad úložisko, kde je všetko nastavené

Zdroj: hab.com