Gebruik Gradle- en Github-aksies om Java-projek na Sonatype Maven Central Repository te publiseer

In hierdie artikel wil ek 'n gedetailleerde kyk na die proses om 'n Java-artefak van nuuts af te publiseer deur Github Actions na die Sonatype Maven Central Repository met behulp van die Gradle-bouer.

Ek het besluit om hierdie artikel te skryf weens die gebrek aan 'n normale tutoriaal op een plek. Al die inligting moes stuk-stuk uit verskeie bronne versamel word, boonop nie heeltemal vars nie. Wie gee om, welkom onder kat.

Skep 'n bewaarplek in Sonatype

Die eerste stap is om 'n bewaarplek in Sonatype Maven Central te skep. Hiervoor gaan ons hier, registreer en skep 'n nuwe taak, en vra ons om 'n bewaarplek te skep. Ons ry in ons Groep-ID projek, Projek-URL projek skakel en SCM url 'n skakel na die weergawebeheerstelsel waarin die projek geleë is. Groep-ID hier moet van die vorm wees com.example, com.example.domain, com.example.testsupport, en kan ook in die vorm van 'n skakel na jou github wees: github.com/yourusername -> io.github.yourusername. Jy sal in elk geval eienaarskap van hierdie domein of profiel moet verifieer. As u 'n github-profiel gespesifiseer het, sal u gevra word om 'n publieke bewaarplek met die gewenste naam te skep.

'n Rukkie na bevestiging sal jou GroupId geskep word en ons kan aanbeweeg na die volgende stap, Gradle-konfigurasie.

Stel Gradle op

Met die skryf hiervan het ek nie Gradle-inproppe gevind wat kan help met die publisering van die artefak nie. Dit die enigste inprop wat ek gevind het, het die skrywer egter geweier om dit verder te ondersteun. Daarom het ek besluit om alles self te doen, aangesien dit nie te moeilik is om dit te doen nie.

Die eerste ding om uit te vind is Sonatype se vereistes vir publikasie. Hulle is die volgende:

  • Beskikbaarheid van bronkodes en JavaDoc, dws. moet bywoon -sources.jar и-javadoc.jar lêers. Soos in die dokumentasie genoem, as dit nie moontlik is om bronkodes of dokumentasie te verskaf nie, kan jy 'n dummy maak -sources.jar of -javadoc.jar met 'n eenvoudige README binne om die toets te slaag.
  • Alle lêers moet onderteken word met GPG/PGPEn .asc die lêer wat die handtekening bevat, moet by elke lêer ingesluit word.
  • Beskikbaarheid pom lêer
  • Korrekte waardes groupId, artifactId и version. Die weergawe kan 'n arbitrêre string wees en kan nie eindig met -SNAPSHOT
  • Teenwoordigheid vereis name, description и url
  • Die teenwoordigheid van inligting oor die lisensie, ontwikkelaars en weergawebeheerstelsel

Dit is die basiese reëls wat gevolg moet word wanneer jy publiseer. Volledige inligting beskikbaar hier.

Ons implementeer hierdie vereistes in build.gradle lêer. Kom ons voeg eers al die nodige inligting oor die ontwikkelaars, lisensies, weergawebeheerstelsel by, en stel ook die url, naam en beskrywing van die projek in. Kom ons skryf 'n eenvoudige metode hiervoor:

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

Vervolgens moet u dit spesifiseer tydens die samestelling wat gegenereer is -sources.jar и-javadoc.jar lêers. Vir hierdie afdeling java jy moet die volgende byvoeg:

java {
    withJavadocJar()
    withSourcesJar()
}

Kom ons gaan aan na die laaste vereiste, die opstel van 'n GPG/PGP-handtekening. Om dit te doen, koppel die inprop signing:

plugins {
    id 'signing'
}

En voeg 'n afdeling by:

signing {
    sign publishing.publications
}

Laastens, laat ons 'n afdeling byvoeg 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
            }
        }
    }
}

Hier sonatipe Gebruikersnaam и sonatipe Wagwoord veranderlikes wat die aanmelding en wagwoord bevat wat geskep is tydens registrasie op sonatype.org.

Dus die eindstryd build.gradle sal so lyk:

Volledige bou.gradle-kode

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

Ek wil daarop let dat ons die weergawe van die omgewingsveranderlike kry: System.getenv('RELEASE_VERSION'). Ons sal dit tydens samestelling blootstel en dit van die merkernaam neem.

PGP-sleutelgenerering

Een van Sonatype se vereistes is dat alle lêers met 'n GPG/PGP-sleutel onderteken moet word. Hiervoor gaan ons hier en laai die GnuPG-nutsding vir jou bedryfstelsel af.

  • Ons genereer 'n sleutelpaar: gpg --gen-key, voer 'n gebruikersnaam, e-posadres in en stel ook 'n wagwoord in.
  • Ons vind uit id ons sleutel met die opdrag: gpg --list-secret-keys --keyid-format short. ID sal na die skuinsstreep gespesifiseer word, byvoorbeeld: rsa2048/9B695056
  • Publiseer die publieke sleutel na die bediener https://keys.openpgp.org met die opdrag: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Ons voer die geheime sleutel na 'n arbitrêre plek uit, ons sal dit in die toekoms nodig hê: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Stel Github Actions op

Kom ons gaan aan na die finale stadium, stel die bou op en publiseer outomaties met Github Actions.
Github Actions is 'n kenmerk waarmee u die werkvloei kan outomatiseer deur 'n volledige CI / CD-siklus te implementeer. Bou, toets en ontplooi kan deur verskeie gebeurtenisse geaktiveer word: kodedruk, vrystellingskepping of kwessies. Hierdie funksionaliteit is absoluut gratis vir openbare bewaarplekke.

In hierdie afdeling sal ek jou wys hoe om bou- en stootkode op te stel en na die Sonatype-bewaarplek te ontplooi by vrystelling, sowel as om geheime op te stel.

Ons stel geheime vas

Vir outomatiese samestelling en ontplooiing het ons 'n aantal geheime waardes nodig, soos die sleutel-ID, die wagwoord wat ons ingevoer het toe ons die sleutel genereer het, die PGP-sleutel self en die Sonatype-aanmelding/wagwoord. U kan dit in 'n spesiale afdeling in die bewaarplekinstellings stel:

Gebruik Gradle- en Github-aksies om Java-projek na Sonatype Maven Central Repository te publiseer

Ons stel die volgende veranderlikes:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - login / wagwoord wat ons ingevoer het toe ons by Sonatype geregistreer het
  • SIGNING_KEYID/SIGNING_PASSWORD — PGP-sleutel-ID en wagwoord gestel tydens generering.

Ek wil in meer besonderhede stilstaan ​​by die GPG_KEY_CONTENTS veranderlike. Die feit is dat ons 'n private PGP-sleutel nodig het vir publikasie. Om dit in die geheime te plaas, het ek gebruik instruksies en het ook 'n aantal aksies gemaak.

  • Kom ons enkripteer ons sleutel met gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgdeur 'n wagwoord in te voer. Dit moet in 'n veranderlike geplaas word: SECRET_PASSPHRASE
  • Kom ons vertaal die ontvang geënkripteerde sleutel in 'n teksvorm met behulp van base64: base64 9B695056.gpg.gpg > 9B695056.txt. Die inhoud sal in die veranderlike geplaas word: GPG_KEY_CONTENTS.

Bou opstelling wanneer kode gedruk word en PR skep

Eerstens moet jy 'n vouer in die wortel van jou projek skep: .github/workflows.

Merk die lêer daarin, byvoorbeeld, gradle-ci-build.yml met die volgende inhoud:

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

Hierdie werkvloei sal uitgevoer word wanneer na takke gedruk word master, dev и testing, ook wanneer trekversoeke geskep word.

Die werksafdeling spesifiseer die stappe wat uitgevoer moet word op die gespesifiseerde gebeurtenisse. In hierdie geval sal ons voortbou op die nuutste weergawe van ubuntu, Java 8 gebruik, en ook die inprop vir Gradle gebruik eskatos/gradle-command-action@v1wat, met die nuutste weergawe van die bouer, die opdragte sal uitvoer wat in arguments. Veranderlikes secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD dit is die geheime wat ons vroeër gevra het.

Die bouresultate sal in die Actions-oortjie weerspieël word:

Gebruik Gradle- en Github-aksies om Java-projek na Sonatype Maven Central Repository te publiseer

Outo-ontplooi wanneer 'n nuwe vrystelling vrygestel word

Kom ons skep 'n aparte werkvloeilêer vir outo-ontplooiing 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}}

Die lêer is amper identies aan die vorige een, behalwe vir die gebeurtenis waarin dit geaktiveer sal word. In hierdie geval is dit die geval van die skep van 'n merker met 'n naam wat met v begin.

Voor ontplooiing moet ons die PGP-sleutel uit die geheime onttrek en dit in die wortel van die projek plaas, asook dit dekripteer. Vervolgens moet ons 'n spesiale omgewingsveranderlike stel RELEASE_VERSION waarna ons verwys gradle.build lêer. Dit alles word in die afdeling gedoen Prepare to publish. Ons kry ons sleutel van die GPG_KEY_CONTENTS veranderlike, vertaal dit in 'n gpg lêer, en dekripteer dit dan deur dit in die lêer te plaas secret.gpg.

Vervolgens gaan ons na 'n spesiale veranderlike GITHUB_REF, waaruit ons die weergawe kan kry wat ons gestel het toe ons die merker skep. Hierdie veranderlike is in hierdie geval relevant. refs/tags/v0.0.2 waaruit ons die eerste 11 karakters afgesny het om 'n spesifieke weergawe te kry. Vervolgens gebruik ons ​​die standaard Gradle-opdragte vir publisering: test publish

Die nagaan van ontplooiingsresultate in Sonatype-bewaarplek

Nadat die vrystelling geskep is, moet die werkvloei wat in die vorige afdeling beskryf is, begin. Om dit te doen, skep 'n vrystelling:

Gebruik Gradle- en Github-aksies om Java-projek na Sonatype Maven Central Repository te publiseer

die merkernaam moet met v begin. As, nadat ons op Publiseer vrystelling geklik het, die werkvloei suksesvol voltooi is, kan ons gaan na Sonatype Nexus om seker te maak:

Gebruik Gradle- en Github-aksies om Java-projek na Sonatype Maven Central Repository te publiseer

Die artefak het in die Staging-bewaarplek verskyn. Dit verskyn onmiddellik in die Oop-status, dan moet dit met die hand na die Toe-status oorgedra word deur die toepaslike knoppie te druk. Nadat gekontroleer is dat aan alle vereistes voldoen word, gaan die artefak na die Close-status en is dit nie meer beskikbaar vir wysiging nie. In hierdie vorm sal dit in MavenCentral beland. As alles goed is, kan jy die knoppie druk Release, en die artefak sal in die Sonatype-bewaarplek beland.

Om die artefak in MavenCentral te laat kom, moet jy daarvoor vra in die taak wat ons heel aan die begin geskep het. Jy hoef dit net een keer te doen, so ons publiseer vir die eerste keer. In die daaropvolgende tye is dit nie nodig nie, alles sal outomaties gesinchroniseer word. Hulle het sinchronisasie vinnig vir my aangeskakel, maar dit het ongeveer 5 dae geneem voordat die artefak in MavenCentral beskikbaar was.

Dit is al, ons het ons artefak in MavenCentral gepubliseer.

nuttige skakels

  • Soortgelyk статья, publiseer slegs via maven
  • Stellasies bewaarplek Sonatipe
  • jira Sonatipe waarin die taak geskep moet word
  • Voorbeeld bewaarplek waar dit alles opgestel is

Bron: will.com