Gradle en Github-aksjes brûke om Java-projekt te publisearjen nei Sonatype Maven Central Repository

Yn dit artikel wol ik it proses fan it publisearjen fan in Java-artefakt fanôf it begjin fia Github Actions yn 'e Sonatype Maven Central Repository mei de Gradle-samler besjen.

Ik besleat dit artikel te skriuwen fanwegen it gebrek oan in normale tutorial op ien plak. Alle ynformaasje moast stik foar stik út ferskate boarnen sammele wurde, en net hielendal resinte. Wa makket it út, wolkom ûnder kat.

It meitsjen fan in repository yn Sonatype

De earste stap is om in repository te meitsjen yn Sonatype Maven Central. Hjirfoar geane wy hjir, registrearje en meitsje in nije taak, freegje ús om in repository te meitsjen. Wy ride yn ús GroupId projekt, URL fan projekt keppeling nei it projekt en SCM url in keppeling nei it ferzjekontrôlesysteem wêryn it projekt leit. GroupId hjir moat wêze lykas com.example, com.example.domain, com.example.testsupport, en kin ek wêze yn 'e foarm fan in keppeling nei jo github: github.com/yourusername -> io.github.yourusername. Yn alle gefallen moatte jo it eigendom fan it domein of profyl ferifiearje. As jo ​​in Github-profyl opjûn hawwe, sil jo frege wurde om in iepenbier repository te meitsjen mei de winske namme.

In skoft nei befêstiging sil jo GroupId oanmakke wurde en kinne wy ​​trochgean nei de folgjende stap, Gradle-konfiguraasje.

Gradle konfigurearje

Op it stuit fan skriuwen fûn ik gjin plugins foar Gradle dy't koe helpe by it publisearjen fan in artefakt. dizze de ienige plugin dy't ik fûn, mar de skriuwer wegere it fierder te stypjen. Dêrom besleat ik alles sels te dwaan, lokkich is it net te dreech.

It earste ding om út te finen is de publikaasjeeasken fan Sonatype. Se binne as folget:

  • Beskikberens fan boarne koades en JavaDoc, i.e. bywenje moatte -sources.jar и-javadoc.jar triemmen. Lykas oanjûn yn 'e dokumintaasje, as it net mooglik is om boarnekoades of dokumintaasje te leverjen, kinne jo in dummy meitsje -sources.jar of -javadoc.jar mei in ienfâldige README binnen om ferifikaasje troch te jaan.
  • Alle triemmen moatte wurde ûndertekene mei GPG/PGPen .asc it bestân mei de hantekening moat foar elk bestân opnommen wurde.
  • beskikberens pom map
  • Korrekte wearden groupId, artifactId и version. Ferzje kin in willekeurige tekenrige wêze en kin net einigje mei -SNAPSHOT
  • Oanwêzigens nedich name, description и url
  • De oanwêzigens fan ynformaasje oer de lisinsje, ûntwikkelders en ferzjekontrôlesysteem

Dit binne de basisregels dy't moatte wurde folge by it publisearjen. Folsleine ynformaasje beskikber hjir.

Wy implementearje dizze easken yn build.gradle map. Lit ús earst alle nedige ynformaasje tafoegje oer de ûntwikkelders, lisinsje, ferzjekontrôlesysteem, en ek de url, namme en beskriuwing fan it projekt ynstelle. Om dit te dwaan, litte wy in ienfâldige metoade skriuwe:

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

Folgjende moatte jo oanjaan dat se sille generearje tidens de gearkomste -sources.jar и-javadoc.jar triemmen. Om dit te dwaan, gean nei de seksje java jo moatte it folgjende tafoegje:

java {
    withJavadocJar()
    withSourcesJar()
}

Litte wy trochgean nei de lêste eask, it ynstellen fan in GPG / PGP-hântekening. Om dit te dwaan, litte wy de plugin ferbine signing:

plugins {
    id 'signing'
}

En foegje in seksje ta:

signing {
    sign publishing.publications
}

As lêste, litte wy in seksje tafoegje 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
            }
        }
    }
}

it is sonatypeUsername и sonatypeWachtwurd fariabelen mei dêryn de oanmelden en wachtwurd makke by registraasje op sonatype.org.

De finale dus build.gradle sil der sa útsjen:

Folsleine build.gradle koade

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

Ik wol opmerke dat wy de ferzje krije fan 'e omjouwingsfariabele: System.getenv('RELEASE_VERSION'). Wy sille it ynstelle by de montage en nimme it fan 'e tagnamme.

PGP kaai generaasje

Ien fan Sonatype's easken is dat alle bestannen wurde tekene mei in GPG/PGP-kaai. Hjirfoar geane wy hjir en download it GnuPG-hulpprogramma foar jo bestjoeringssysteem.

  • Wy generearje in kaaipaar: gpg --gen-key, Fier jo brûkersnamme, e-post yn en set ek in wachtwurd yn.
  • Litte wy útfine id ús kaai mei it kommando: gpg --list-secret-keys --keyid-format short. Id sil wurde opjûn nei de slash, bygelyks: rsa2048/9B695056
  • Publisearjen fan de iepenbiere kaai nei de tsjinner https://keys.openpgp.org befel: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Wy eksportearje de geheime kaai nei in willekeurige lokaasje; wy sille it letter nedich wêze: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Github-aksjes ynstelle

Litte wy trochgean nei it lêste poadium, it ynstellen fan de build en auto-publisearjen mei Github Actions.
Github Actions is in funksjonaliteit wêrmei jo de workflow kinne automatisearje troch it útfieren fan in folsleine CI / CD-syklus. Bouwe, testen en ynset kinne wurde trigger troch ferskate eveneminten: koade drukke, in release oanmeitsje of problemen. Dizze funksjonaliteit is absolút fergees foar iepenbiere repositories.

Yn dizze seksje sil ik jo sjen litte hoe't jo de build en push fan koade en ynset ynstelle nei it Sonatype-repository by it frijjaan fan in release, lykas ek geheimen ynstelle.

Wy sette geheimen

Foar automatyske gearstalling en ynset sille wy in oantal geheime wearden nedich hawwe, lykas de kaai-id, it wachtwurd dat wy ynfierd hawwe by it generearjen fan de kaai, de PGP-kaai sels, en ek de oanmelding/wachtwurd foar Sonatype. Jo kinne se yn in spesjale seksje ynstelle yn 'e repository-ynstellingen:

Gradle en Github-aksjes brûke om Java-projekt te publisearjen nei Sonatype Maven Central Repository

Wy sette de folgjende fariabelen:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - oanmelding / wachtwurd dat wy ynfierd hawwe by registrearjen by Sonatype
  • SIGNING_KEYID / SIGNING_PASSWORD - PGP-kaai-id en wachtwurd ynsteld tidens generaasje.

Ik soe graach wenje op de GPG_KEY_CONTENTS fariabele yn mear detail. It feit is dat wy in privee PGP-kaai nedich om te publisearjen. Om it yn 'e geheimen te pleatsen, brûkte ik ynstruksje en hat boppedat in oantal aksjes dien.

  • Litte wy ús kaai fersiferje mei gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgtroch it ynfieren fan in wachtwurd. It moat wurde pleatst yn in fariabele: SECRET_PASSPHRASE
  • Litte wy de ûntfongen fersifere kaai oersette yn in tekstfoarm mei base64: base64 9B695056.gpg.gpg > 9B695056.txt. Wy pleatse de ynhâld yn 'e fariabele: GPG_KEY_CONTENTS.

It ynstellen fan in build by it triuwen fan koade en it meitsjen fan in PR

Earst moatte jo in map meitsje yn 'e root fan jo projekt: .github/workflows.

Markearje it bestân dêryn, bygelyks, gradle-ci-build.yml mei de folgjende ynhâld:

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

Dizze workflow sil wurde útfierd as jo nei tûken drukke master, dev и testing, ek by it meitsjen fan pull-oanfragen.

De seksje banen spesifisearret de stappen dy't moatte wurde útfierd op de opjûne eveneminten. Yn dit gefal sille wy bouwe op 'e lêste ferzje fan ubuntu, Java 8 brûke, en ek in plugin brûke foar Gradle eskatos/gradle-command-action@v1, dy't, mei de lêste ferzje fan 'e samler, de kommando's sil útfiere oantsjutte yn arguments. Fariabelen secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD dit binne de geheimen dy't wy earder fregen.

De bouresultaten sille wurde wjerspegele yn it ljepblêd Aksjes:

Gradle en Github-aksjes brûke om Java-projekt te publisearjen nei Sonatype Maven Central Repository

Automatysk ynsette as in nije release wurdt frijlitten

Foar autodeployment sille wy in apart workflow-bestân meitsje 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}}

De triem is hast identyk oan de foarige, útsein foar it barren wêrop it sil wurde trigger. Yn dit gefal is dit it barren fan it meitsjen fan in tag mei in namme dy't begjint mei v.

Foar de ynset moatte wy de PGP-kaai út 'e geheimen ekstrahearje en it yn 'e projektroot pleatse, en ek it ûntsiferje. Dêrnei moatte wy in spesjale omjouwingsfariabele ynstelle RELEASE_VERSION dêr't wy nei ferwize gradle.build map. Dit alles wurdt dien yn 'e seksje Prepare to publish. Wy krije ús kaai fan de fariabele GPG_KEY_CONTENTS, oersette it yn in gpg-bestân, en ûntsiferje it dan troch it yn it bestân te pleatsen secret.gpg.

Folgjende, wy keare nei in spesjale fariabele GITHUB_REF, wêrfan wy de ferzje kinne krije dy't wy ynsteld hawwe by it meitsjen fan de tag. Dizze fariabele yn dit gefal hat de wearde refs/tags/v0.0.2 wêrfan wy de earste 11 karakters ôfsnije om de spesifike ferzje te krijen. Dêrnei brûke wy de standert Gradle-kommando's foar publisearjen: test publish

It kontrolearjen fan ynsetresultaten yn it Sonatype-repository

Nei it oanmeitsjen fan de release moat de workflow beskreaun yn 'e foarige seksje begjinne. Om dit te dwaan, meitsje in release:

Gradle en Github-aksjes brûke om Java-projekt te publisearjen nei Sonatype Maven Central Repository

yn dit gefal moat de tagnamme begjinne mei v. As, nei it klikken op Publisearje release, de workflow mei súkses rint, kinne wy ​​​​gean nei Sonatype Nexus om der wis fan te wêzen:

Gradle en Github-aksjes brûke om Java-projekt te publisearjen nei Sonatype Maven Central Repository

It artefakt ferskynde yn 'e Staging-repository. It ferskynt fuortendaliks yn 'e status Iepenje, dan moat it mei de hân wurde oerbrocht nei de status slute troch op de oerienkommende knop te klikken. Nei it kontrolearjen dat alle easken foldien binne, ferpleatst it artefakt nei de status slute en is net mear beskikber foar wiziging. Yn dizze foarm sil it einigje yn MavenCentral. As alles goed is, kinne jo op de knop drukke release, en it artefakt sil nei it Sonatype-repository gean.

Om it artefakt op te nimmen yn MavenCentral, moatte jo dernei freegje yn 'e taak dy't wy oan it begjin makke hawwe. Jo hoege dit mar ien kear te dwaan, dus publisearje wy foar it earst. D'r is gjin need om dit de folgjende kear te dwaan, alles sil automatysk syngronisearre wurde. Se skeakelen syngronisaasje foar my fluch oan, mar it duorre sawat 5 dagen foar it artefakt beskikber te wurden yn MavenCentral.

Dat is alles, wy hawwe ús artefakt publisearre yn MavenCentral.

Nuttige keppelings

  • Similar artikel, allinich publisearje fia maven
  • Staging repository Sonatype
  • Jira Sonatype wêryn de taak te meitsjen
  • Foarbyld: repository wêr't it allegear ynsteld is

Boarne: www.habr.com