Verwenden von Gradle- und Github-Aktionen zum Veröffentlichen eines Java-Projekts im Sonatype Maven Central Repository

In diesem Artikel möchte ich einen detaillierten Blick auf den Prozess des Publizierens eines Java-Artefakts von Grund auf über Github-Aktionen im Sonatype Maven Central Repository mit dem Gradle-Kollektor werfen.


Ich habe mich entschlossen, diesen Artikel zu schreiben, da an einer Stelle kein normales Tutorial vorhanden ist. Alle Informationen mussten in Stücken aus verschiedenen Quellen gesammelt werden, obwohl sie nicht ganz frisch waren. Wen kümmert es, willkommen bei Katze.


Erstellen eines Repositorys in Sonatype


Der erste Schritt besteht darin, ein Repository in Sonatype Maven Central zu erstellen. Gehen Sie dazu hierher , registrieren Sie sich und erstellen Sie eine neue Aufgabe. Bitten Sie uns, ein Repository für uns zu erstellen. Wir fahren unsere GroupId des Projekts, den Projekt-URL- Link zum Projekt und den SCM-URL- Link zum Versionskontrollsystem ein, in dem sich das Projekt befindet. Die GroupId hier sollte die Form com.example, com.example.domain, com.example.testsupport haben und kann auch ein Link zu Ihrem github sein: github.com/yourusername -> io.github.yourusername. In jedem Fall müssen Sie den Besitz dieser Domain oder dieses Profils bestätigen. Wenn Sie ein Github-Profil angegeben haben, werden Sie aufgefordert, ein öffentliches Repository mit dem gewünschten Namen zu erstellen.


Einige Zeit nach der Bestätigung wird Ihre GroupId erstellt und wir können mit dem nächsten Schritt, der Gradle-Konfiguration, fortfahren.


Gradle konfigurieren


Zum Zeitpunkt dieses Schreibens habe ich keine Plugins für Gradle gefunden, die bei der Veröffentlichung des Artefakts helfen könnten. Dies ist das einzige Plugin, das ich gefunden habe, jedoch hat der Autor seine weitere Unterstützung abgelehnt. Deshalb habe ich beschlossen, alles selbst zu machen, da es nicht allzu schwierig ist, es zu tun.


Das erste, was Sie herausfinden müssen, sind die Veröffentlichungsanforderungen von Sonatype. Sie sind wie folgt:


  • Das Vorhandensein von Quellcodes und JavaDoc, d.h. muss vorhanden sein -sources.jarund -javadoc.jarDateien. Wie in der Dokumentation angegeben, können Sie einen Dummy -sources.jaroder -javadoc.jareine einfache README-Datei erstellen, um den Test zu bestehen , wenn es nicht möglich ist, Quellcodes oder Dokumentation bereitzustellen .
  • GPG/PGP, .asc , , .
  • pom
  • groupId, artifactId version. -SNAPSHOT
  • name, description url
  • ,

, . .


build.gradle . , , , url, . :


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@dev.ru'
                }
            }
        }
    }
}

, -sources.jar -javadoc.jar . java :


java {
    withJavadocJar()
    withSourcesJar()
}

, GPG/PGP . signing:


plugins {
    id 'signing'
}

:


signing {
    sign publishing.publications
}

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

sonatypeUsername sonatypePassword , , sonatype.org.


, build.gradle :


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@dev.ru'
                }
            }
        }
    }
}

, : System.getenv('RELEASE_VERSION'). .


PGP


Sonatype GPG/PGP . GnuPG .


  • : gpg --gen-key, , e-mail, .
  • id : gpg --list-secret-keys --keyid-format short. Id , : rsa2048/9B695056
  • https://keys.openpgp.org : gpg --keyserver https://keys.openpgp.org/ --send-keys 9B695056
  • , : gpg --export-secret-key 9B695056 > D:\\gpg\\9B695056.gpg

Github Actions


, , Github Actions.
Github Actions – , , CI/CD. , : , issues. .


Sonatype , .



, id , , , PGP , / Sonatype. :



:


  • SONATYPE_USERNAME/SONATYPE_PASSWORD — /, Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — id PGP , .

GPG_KEY_CONTENTS . , PGP . , , .


  • gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, . : SECRET_PASSPHRASE
  • base64: base64 9B695056.gpg.gpg > 9B695056.txt. : GPG_KEY_CONTENTS.

PR


: .github/workflows.


, , gradle-ci-build.yml :


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

master, dev testing, .


jobs , . ubuntu, Java 8, Gradle eskatos/gradle-command-action@v1, , arguments. secrets.SONATYPE_USERNAME secrets.SONATYPE_PASSWORD , .


Actions:




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

, . , v.


PGP , . RELEASE_VERSION gradle.build . Prepare to publish. GPG_KEY_CONTENTS, gpg , , secret.gpg.


GITHUB_REF, , . refs/tags/v0.0.2 11 , . Gradle : test publish


Sonatype


, . :



v. Publish release, , Sonatype Nexus :



Staging . Open, Close, . , Close . MavenCentral. , Release, Sonatype.


, MavenCentral, , . , . , . , MavenCentral 5 .


Das ist alles, wir haben unser Artefakt in MavenCentral veröffentlicht.


Nützliche Links


  • Ähnlicher Artikel , nur Veröffentlichung über Maven
  • Staging- Repository- Sonatyp
  • Jira Sonatype, in dem Sie eine Aufgabe erstellen müssen
  • Ein Beispiel- Repository, in dem dies alles eingerichtet ist

All Articles