Përdorimi i Veprimeve Gradle dhe Github për të publikuar Projektin Java në Depon Qendrore të Sonatype Maven

Në këtë artikull, unë dua të hedh një vështrim më të afërt në procesin e publikimit të një artifakti Java nga e para përmes Veprimeve të Github në Depon Qendrore Sonatype Maven duke përdorur ndërtuesin Gradle.

Vendosa ta shkruaj këtë artikull për shkak të mungesës së një tutoriali normal në një vend. I gjithë informacioni duhej mbledhur pjesë-pjesë nga burime të ndryshme, për më tepër, jo plotësisht i freskët. Kush kujdeset, mirëpritur nën mace.

Krijimi i një depoje në Sonatype

Hapi i parë është krijimi i një depoje në Sonatype Maven Central. Për këtë shkojmë këtu, regjistrohuni dhe krijoni një detyrë të re, duke na kërkuar të krijojmë një depo. Ne vozisim me makinën tonë ID e grupit projekti, URL e projektit lidhjen e projektit dhe SCM url një lidhje me sistemin e kontrollit të versionit në të cilin ndodhet projekti. ID e grupit këtu duhet të jetë e formës com.example, com.example.domain, com.example.testsupport, dhe gjithashtu mund të jetë në formën e një lidhjeje me github-in tuaj: github.com/emri juaj i përdoruesit -> io.github.emri juaj i përdoruesit. Në çdo rast, do t'ju duhet të verifikoni pronësinë e këtij domeni ose profili. Nëse keni specifikuar një profil github, do t'ju kërkohet të krijoni një depo publike me emrin e dëshiruar.

Disa kohë pas konfirmimit, GroupId-i juaj do të krijohet dhe ne mund të kalojmë në hapin tjetër, konfigurimin e Gradle.

Konfigurimi i Gradle

Në kohën e shkrimit, nuk gjeta shtojca Gradle që mund të ndihmonin me publikimin e artefaktit. Ajo të vetmen shtojcë që gjeta, megjithatë, autori refuzoi ta mbështeste më tej. Prandaj, vendosa të bëj gjithçka vetë, pasi nuk është shumë e vështirë ta bësh këtë.

Gjëja e parë që duhet kuptuar janë kërkesat e Sonatype për botimin. Ato janë këto:

  • Disponueshmëria e kodeve burimore dhe JavaDoc, dmth. duhet të marrë pjesë -sources.jar и-javadoc.jar dosjet. Siç thuhet në dokumentacion, nëse nuk është e mundur të jepni kodet burimore ose dokumentacionin, mund të bëni një bedel -sources.jar ose -javadoc.jar me një README të thjeshtë brenda për të kaluar testin.
  • Të gjithë skedarët duhet të nënshkruhen me GPG/PGPDhe .asc dosja që përmban nënshkrimin duhet të përfshihet për çdo skedar.
  • Disponueshmëria pom dosje
  • vlerat e sakta groupId, artifactId и version. Versioni mund të jetë një varg arbitrar dhe nuk mund të përfundojë me -SNAPSHOT
  • Kërkohet prania name, description и url
  • Prania e informacionit në lidhje me licencën, zhvilluesit dhe sistemin e kontrollit të versionit

Këto janë rregullat bazë që duhen ndjekur gjatë publikimit. Informacioni i plotë në dispozicion këtu.

Ne i zbatojmë këto kërkesa në build.gradle dosje. Së pari, le të shtojmë të gjithë informacionin e nevojshëm në lidhje me zhvilluesit, licencat, sistemin e kontrollit të versionit, si dhe të vendosim url-në, emrin dhe përshkrimin e projektit. Le të shkruajmë një metodë të thjeshtë për këtë:

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

Tjetra, duhet të specifikoni se gjatë montimit të krijuar -sources.jar и-javadoc.jar dosjet. Për këtë seksion java ju duhet të shtoni sa vijon:

java {
    withJavadocJar()
    withSourcesJar()
}

Le të kalojmë te kërkesa e fundit, vendosja e një nënshkrimi GPG/PGP. Për ta bërë këtë, lidhni shtojcën signing:

plugins {
    id 'signing'
}

Dhe shtoni një seksion:

signing {
    sign publishing.publications
}

Së fundi, le të shtojmë një seksion 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
            }
        }
    }
}

Këtu sonatypeEmri i përdoruesit и sonatypePassword variablat që përmbajnë hyrjen dhe fjalëkalimin e krijuar gjatë regjistrimit në sonatype.org.

Kështu finalja build.gradle do të duket kështu:

Kodi i plotë 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]'
                }
            }
        }
    }
}

Dua të vërej se ne marrim versionin nga ndryshorja e mjedisit: System.getenv('RELEASE_VERSION'). Ne do ta ekspozojmë atë gjatë montimit dhe do ta marrim nga emri i etiketës.

Gjenerimi i çelësave PGP

Një nga kërkesat e Sonatype është që të gjithë skedarët të nënshkruhen me një çelës GPG/PGP. Për këtë shkojmë këtu dhe shkarkoni mjetin GnuPG për sistemin tuaj operativ.

  • Ne gjenerojmë një çift çelësash: gpg --gen-key, futni një emër përdoruesi, e-mail dhe vendosni gjithashtu një fjalëkalim.
  • Ne e zbulojmë id çelësi ynë me komandën: gpg --list-secret-keys --keyid-format short. ID-ja do të specifikohet pas vijës së pjerrët, për shembull: rsa2048/9B695056
  • Publikimi i çelësit publik në server https://keys.openpgp.org me komandën: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Ne e eksportojmë çelësin sekret në një vend arbitrar, do të na duhet në të ardhmen: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Konfigurimi i Veprimeve Github

Le të kalojmë në fazën përfundimtare, të konfigurojmë ndërtimin dhe të publikojmë automatikisht duke përdorur Veprimet e Github.
Github Actions është një veçori që ju lejon të automatizoni rrjedhën e punës duke zbatuar një cikël të plotë CI / CD. Ndërtimi, testimi dhe vendosja mund të shkaktohet nga ngjarje të ndryshme: shtytja e kodit, krijimi i lëshimit ose problemet. Ky funksionalitet është absolutisht falas për depot publike.

Në këtë seksion, unë do t'ju tregoj se si të konfiguroni kodin e ndërtimit dhe shtyrjes dhe të vendosni në depon e Sonatype pas lëshimit, si dhe të vendosni sekretet.

Ne vendosëm sekrete

Për montimin dhe vendosjen automatike, na duhen një sërë vlerash sekrete, të tilla si id-ja e çelësit, fjalëkalimi që kemi futur gjatë gjenerimit të çelësit, vetë çelësi PGP dhe identifikimi/fjalëkalimi i Sonatype. Ju mund t'i vendosni ato në një seksion të veçantë në cilësimet e depove:

Përdorimi i Veprimeve Gradle dhe Github për të publikuar Projektin Java në Depon Qendrore të Sonatype Maven

Ne vendosëm variablat e mëposhtëm:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - identifikimi / fjalëkalimi që kemi futur gjatë regjistrimit me Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — ID-ja dhe fjalëkalimi i çelësit PGP janë vendosur gjatë gjenerimit.

Unë dua të ndalem në variablin GPG_KEY_CONTENTS në më shumë detaje. Fakti është se për publikim na duhet një çelës privat PGP. Për ta postuar në sekrete, e përdora udhëzime dhe gjithashtu bëri një sërë veprimesh.

  • Le të kodojmë çelësin tonë me gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgduke futur një fjalëkalim. Duhet të vendoset në një variabël: SECRET_PASSPHRASE
  • Le ta përkthejmë çelësin e koduar të marrë në një formë teksti duke përdorur base64: base64 9B695056.gpg.gpg > 9B695056.txt. Përmbajtja do të vendoset në variablin: GPG_KEY_CONTENTS.

Ndërtoni konfigurimin kur shtypni kodin dhe krijoni PR

Së pari ju duhet të krijoni një dosje në rrënjën e projektit tuaj: .github/workflows.

Në të, shënoni skedarin, për shembull, gradle-ci-build.yml me përmbajtjen e mëposhtme:

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

Kjo rrjedhë pune do të ekzekutohet kur shtyhet në degë master, dev и testing, gjithashtu kur krijoni kërkesa për tërheqje.

Seksioni i punëve specifikon hapat që duhet të ekzekutohen në ngjarjet e specifikuara. Në këtë rast, ne do të ndërtojmë versionin më të fundit të ubuntu, do të përdorim Java 8 dhe gjithashtu do të përdorim shtesën për Gradle eskatos/gradle-command-action@v1i cili, duke përdorur versionin më të fundit të ndërtuesit, do të ekzekutojë komandat e specifikuara në arguments. Variablat secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD këto janë sekretet që kemi pyetur më parë.

Rezultatet e ndërtimit do të pasqyrohen në skedën Veprimet:

Përdorimi i Veprimeve Gradle dhe Github për të publikuar Projektin Java në Depon Qendrore të Sonatype Maven

Vendoset automatikisht kur lëshohet një version i ri

Le të krijojmë një skedar të veçantë të rrjedhës së punës për vendosjen automatike 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}}

Skedari është pothuajse identik me atë të mëparshëm, me përjashtim të ngjarjes në të cilën do të aktivizohet. Në këtë rast, kjo është ngjarja e krijimit të një etikete me një emër që fillon me v.

Para vendosjes, ne duhet të nxjerrim çelësin PGP nga sekretet dhe ta vendosim atë në rrënjën e projektit, si dhe ta deshifrojmë atë. Më pas, duhet të vendosim një variabël të veçantë mjedisor RELEASE_VERSION të cilit i referohemi gradle.build dosje. E gjithë kjo bëhet në seksion Prepare to publish. Ne e marrim çelësin tonë nga ndryshorja GPG_KEY_CONTENTS, e përkthejmë atë në një skedar gpg dhe më pas e deshifrojmë duke e vendosur në skedar secret.gpg.

Tjetra, ne i drejtohemi një ndryshoreje të veçantë GITHUB_REF, nga i cili mund të marrim versionin që kemi vendosur gjatë krijimit të etiketës. Ky variabël është i rëndësishëm në këtë rast. refs/tags/v0.0.2 nga i cili kemi prerë 11 karakteret e para për të marrë një version specifik. Më pas, ne përdorim komandat standarde Gradle për publikim: test publish

Kontrollimi i rezultateve të vendosjes në depon e Sonatype

Pas krijimit të lëshimit, rrjedha e punës e përshkruar në seksionin e mëparshëm duhet të fillojë. Për ta bërë këtë, krijoni një version:

Përdorimi i Veprimeve Gradle dhe Github për të publikuar Projektin Java në Depon Qendrore të Sonatype Maven

emri i etiketës duhet të fillojë me v. Nëse, pasi klikojmë Publish release, rrjedha e punës përfundon me sukses, ne mund të shkojmë te Nexus Sonatype për t'u siguruar:

Përdorimi i Veprimeve Gradle dhe Github për të publikuar Projektin Java në Depon Qendrore të Sonatype Maven

Artifakti u shfaq në depon e Staging. Shfaqet menjëherë në statusin e hapur, pastaj duhet të transferohet manualisht në statusin Mbyll duke shtypur butonin përkatës. Pasi të kontrollohet që të gjitha kërkesat janë përmbushur, objekti kalon në statusin Mbyll dhe nuk është më i disponueshëm për modifikim. Në këtë formë, ai do të përfundojë në MavenCentral. Nëse gjithçka është mirë, mund të shtypni butonin Lirimin, dhe objekti do të përfundojë në depon e Sonatype.

Në mënyrë që artifakti të futet në MavenCentral, duhet ta kërkoni atë në detyrën që krijuam që në fillim. Ju duhet ta bëni këtë vetëm një herë, kështu që ne e publikojmë për herë të parë. Në kohët e mëvonshme, kjo nuk kërkohet, gjithçka do të sinkronizohet automatikisht. Ata aktivizuan sinkronizimin për mua shpejt, por u deshën rreth 5 ditë që artifakti të bëhej i disponueshëm në MavenCentral.

Kjo është e gjitha, ne kemi publikuar objektin tonë në MavenCentral.

Lidhje të dobishme

  • i ngjashëm artikull, publikohet vetëm nëpërmjet maven
  • vënie në skenë depo Sonatipi
  • Jira Sonatipi në të cilin do të krijohet detyra
  • Shembull depo ku është e gjitha e vendosur

Burimi: www.habr.com