We gebruiken Gradle en Github Actions voor het publiceren van een Java-project in de Sonatype Maven Central Repository

In dit artikel wil ik gedetailleerd het proces van het publiceren van een Java-artifact via Github Actions in het Sonatype Maven Central Repository met behulp van de Gradle-bouwer bespreken.

Ik besloot dit artikel te schrijven vanwege het gebrek aan een goed tutorial op één plek. Alle informatie moest ik in stukjes verzamelen uit verschillende, niet helemaal actuele bronnen. Voor geïnteresseerden, welkom onder het cat.

Een repository aanmaken in Sonatype

De eerste stap is om een repository aan te maken in het Sonatype Maven Central. Hiervoor gaan we naar hierheen, registreren we ons en creƫren we een nieuwe taak met het verzoek om een repository voor ons aan te maken. We vullen ons GroupId project, Project URL link naar het project en SCM url de link naar het versiebeheersysteem waarin het project zich bevindt. GroupId dit moet van de vorm com.example, com.example.domain, com.example.testsupport zijn, en het kan ook in de vorm van een link naar je GitHub zijn: github.com/yourusername -> io.github.yourusername. In ieder geval moet je het eigendom van dit domein of profiel bevestigen. Als je een GitHub-profiel hebt opgegeven, wordt je gevraagd om een openbaar repository met de benodigde naam aan te maken.

Na enige tijd na bevestiging zal je GroupId zijn aangemaakt en kunnen we doorgaan naar de volgende stap, de configuratie van Gradle.

Gradle configureren

Op het moment van schrijven heb ik geen plugins voor Gradle gevonden die zouden kunnen helpen bij de publicatie van een artifact. Dit is de enige plugin die ik vond, maar de auteur heeft zijn verdere ondersteuning ervan opgezegd. Daarom besloot ik alles zelf te doen, gelukkig is dat niet al te moeilijk.

Het eerste wat moet worden vastgesteld, zijn de eisen van Sonatype voor publicatie. Deze zijn als volgt:

  • Beschikbaarheid van de broncodes en JavaDoc, dat wil zeggen, de volgende moeten aanwezig zijn: -sources.jar en-javadoc.jar bestanden. Zoals in de documentatie staat, als het niet mogelijk is om broncodes of documentatie te verstrekken, kan je een lege dummy maken -sources.jar of -javadoc.jar met een eenvoudig README erin, om door de controle te komen.
  • Alle bestanden moeten worden ondertekend met behulp van GPG/PGP, en .asc bestand dat de ondertekening bevat, moet worden opgenomen voor elk bestand.
  • Aanwezigheid pom bestand
  • Juiste waarden voor groupId, artifactId en version. De versie kan een willekeurige string zijn en mag niet eindigen op -SNAPSHOT
  • Er moet een naam, description en url
  • Zijn aanwezigheid van informatie over licentie, ontwikkelaars en versiebeheersysteem

Dit zijn de belangrijkste regels die moeten worden gevolgd bij publicatie. Volledige informatie is beschikbaar hier.

We implementeren deze vereisten in build.gradle bestand. Laten we beginnen met het toevoegen van alle benodigde informatie over de ontwikkelaars, de licentie, het versiebeheersysteem, en laten we ook de URL, naam en beschrijving van het project instellen. Hiervoor schrijven we een eenvoudige methode:

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

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

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

            description 'Een beschrijving van het artefact'
            name 'Artefact naam'
            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 'DevNaam'
                    email 'email@dev.ru'
                }
            }
        }
    }
}

Vervolgens moet worden aangegeven dat bij het bouwen de -sources.jar en-javadoc.jar bestanden moeten worden gegenereerd. Hiervoor voegen we het volgende toe aan de sectie java java { withJavadocJar() withSourcesJar() }

Laten we overgaan naar de laatste vereiste, het instellen van de GPG/PGP-handtekening. Hiervoor schakelen we de plugin in

signing plugins { id 'signing' }:

En we voegen de sectie toe:

signing { sign publishing.publications }

Tot slot voegen we de sectie

publishing publishing { publications { mavenJava(MavenPublication) { customizePom(pom) groupId group artifactId archivesBaseName version versionfrom components.java } } repositories { maven { url "https://oss.sonatype.org/service/local/staging/deploy/maven2" credentials { username sonatypeUsername password sonatypePassword } } } }:

sonatypeUsername

Hier sonatypePassword en variabelen die de gebruikersnaam en het wachtwoord bevatten, aangemaakt bij registratie op sonatype.org Dus, de uiteindelijke.

Volledige code build.gradle build.gradle ziet er als volgt uit:

Volledige code 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 'Enige beschrijving van het artefact'
            name 'Artifactnaam'
            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 'De Apache License, Versie 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'
                }
            }
        }
    }
}

Ik wil opmerken dat we de versie uit de omgevingsvariabele krijgen: System.getenv('RELEASE_VERSION'). We zullen deze instellen tijdens de build en uit de tagnaam halen.

PGP-sleutel generatie

Een van de vereisten van Sonatype is dat alle bestanden worden ondertekend met behulp van een GPG/PGP-sleutel. Hiervoor gaan we hierheen en downloaden we de GnuPG-tool voor ons besturingssysteem.

  • We genereren een sleutelpaar: gpg --gen-key, voer een gebruikersnaam, e-mailadres in en stel ook een wachtwoord in.
  • We vinden id onze sleutel met de opdracht: gpg --list-secret-keys --keyid-format short. Het ID wordt na de schuin geschreven getoon, bijvoorbeeld: rsa2048/9B695056
  • Publiceer de publieke sleutel op de server https://keys.openpgp.org met het commando: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Exporteer de geheime sleutel naar een willekeurige locatie, deze hebben we later nodig: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Stel Github Actions in

Laten we doorgaan naar de laatste fase, we zullen de build en automatische publicatie instellen met behulp van Github Actions.
Github Actions – een functionaliteit die het mogelijk maakt om werkprocessen te automatiseren en een volledige CI/CD-cyclus te implementeren. Builds, tests en deployments kunnen worden geactiveerd door verschillende gebeurtenissen: codepushes, het maken van releases of issues. Deze functionaliteit is volledig gratis voor openbare repositories.

In dit gedeelte laat ik zien hoe je de build en het pushen van code en de deployment naar een Sonatype-repository kunt instellen bij het uitbrengen van een release, evenals het instellen van geheimen.

Geheimen instellen

Voor automatische builds en deployments hebben we een aantal geheime waardes nodig, zoals de sleutel-ID, het wachtwoord dat we hebben ingevoerd bij het genereren van de sleutel, de daadwerkelijke PGP-sleutel en de inloggegevens voor Sonatype. Deze kunnen worden ingesteld in een speciaal gedeelte van de repository-instellingen:

We gebruiken Gradle en Github Actions voor het publiceren van een Java-project in de Sonatype Maven Central Repository

Stel de volgende variabelen in:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD – inloggegevens die we hebben gebruikt bij de registratie bij Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD – PGP-sleutel-ID en wachtwoord ingesteld bij het genereren.

Laten we wat dieper ingaan op de variabele GPG_KEY_CONTENTS. Het belangrijke is dat we voor publicatie een gesloten PGP-sleutel nodig hebben. Om deze in geheimen op te slaan, heb ik gebruik gemaakt van de instructies en heb ik daarnaast een aantal acties ondernomen.

  • Laten we onze sleutel versleutelen met behulp van gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, voer het wachtwoord in. Dit moet in de variabele worden geplaatst: SECRET_PASSPHRASE
  • Laten we de verkregen versleutelde sleutel omzetten naar tekstformaat met behulp van base64: base64 9B695056.gpg.gpg > 9B695056.txt. Plaats de inhoud in de variabele: GPG_KEY_CONTENTS.

Configuratie van de build bij het pushen van code en het maken van PR

Om te beginnen, moet je een map maken in de root van je project: .github/workflows.

Plaats daar een bestand, bijvoorbeeld, gradle-ci-build.yml met de 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}}

Dit werkproces zal worden uitgevoerd bij het pushen naar de branches master, , maar volgt geen wijzigingen), gebruikmakend van een andere configuratie. en testing, evenals bij het maken van pull requests.

In de jobs-sectie zijn de stappen beschreven die moeten worden uitgevoerd op de opgegeven gebeurtenissen. In dit geval zullen we bouwen op de nieuwste versie van ubuntu, Java 8 gebruiken, en ook de Gradle-plugin gebruiken eskatos/gradle-command-action@v1, die met de laatste versie van de builder de opgegeven commando's zal uitvoeren. argumentsVariabelen secrets.SONATYPE_USERNAME en secrets.SONATYPE_PASSWORD dit zijn geheimen die we eerder hebben ingesteld.

De resultaten van de build worden weergegeven op het tabblad Acties:

We gebruiken Gradle en Github Actions voor het publiceren van een Java-project in de Sonatype Maven Central Repository

Automatisch uitrollen bij nieuwe release

Voor automatische uitrol maken we een apart werkprocessenbestand gradle-ci-publish.yml:

name: publish

on:
  push:
    tags:
      - 'v*'

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

      - name: Voorbereiden om te publiceren
        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: Publiceren met 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}}

Het bestand lijkt praktisch identiek aan het vorige, met uitzondering van de gebeurtenis waarop het geactiveerd wordt. In dit geval is dit de gebeurtenis van het maken van een tag die begint met v.

Voor de uitrol moeten we de PGP-sleutel uit de geheimen halen en deze in de hoofdmap van het project plaatsen, en deze ontcijferen. Vervolgens moeten we een speciale omgevingsvariabele instellen RELEASE_VERSION waarmee we verwijzen naar gradle.build bestand. Dit wordt gedaan in het gedeelte Voorbereiden om te publiceren. We halen onze sleutel uit de variabele GPG_KEY_CONTENTS, zetten deze om in een gpg-bestand, ontcijferen het en plaatsen het in bestand secret.gpg.

Vervolgens verwijzen we naar een speciale variabele GITHUB_REF, waarvan we de versie kunnen halen die we hebben ingesteld bij het maken van de tag. Deze variabele heeft in dit geval de waarde refs/tags/v0.0.2 waarvan we de eerste 11 tekens afsnijden om precies de versie te krijgen. Vervolgens gebruiken we standaard Gradle-commando's voor publicatie: test publish

Controleer de uitrolresultaten in de Sonatype-repository

Na het maken van de release moet het werkproces dat in het vorige gedeelte is beschreven worden gestart. Maak hiervoor een release:

We gebruiken Gradle en Github Actions voor het publiceren van een Java-project in de Sonatype Maven Central Repository

waarbij de tagnaam met v moet beginnen. Als het werkproces succesvol draait na het klikken op Release publiceren, kunnen we naar Sonatype Nexus gaan om dit te bevestigen:

We gebruiken Gradle en Github Actions voor het publiceren van een Java-project in de Sonatype Maven Central Repository

Het artefact is verschenen in de Staging-repository. Het verschijnt direct in de status Open, waarna het handmatig naar de status Close moet worden verplaatst door op de bijbehorende knop te drukken. Nadat alle vereisten zijn gecontroleerd, gaat het artefact naar de status Close en is het niet meer beschikbaar voor wijzigingen. In deze vorm zal het in MavenCentral terechtkomen. Als alles in orde is, kan de knop worden ingedrukt. Release, waarbij het artefact in de Sonatype-repository terechtkomt.

Om het artefact in MavenCentral te krijgen, moet je dit aanvragen in de taak die we in het begin hebben aangemaakt. Dit moet maar ƩƩn keer gedaan worden, omdat we dit voor de eerste keer publiceren. Bij volgende keren is dit niet nodig, alles zal automatisch synchroniseren. De synchronisatie werd snel ingeschakeld, maar het duurde ongeveer 5 dagen voordat het artefact beschikbaar was in MavenCentral.

Dat is alles, we hebben ons artefact gepubliceerd in MavenCentral.

Nuttige links

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster