Përdorim Gradle dhe Github Actions për publikimin e një projekti Java në Sonatype Maven Central Repository

Në këtë artikull, do të shqyrtoj procesin e publikimit nga e para të një artefakti Java përmes Github Actions në Repositorin Qendror të Maven në Sonatype duke përdorur ndihmësin Gradle.

E shkrova këtë artikull për shkak të mungesës së një tutoriali të mirë në një vend. Të gjitha informacionet duhej të mblidheshin në copa nga burime të ndryshme, dhe ato nuk ishin gjithmonë të freskëta. Nëse jeni të interesuar, ju lutem shihni më poshtë.

Krijimi i Repositorit në Sonatype

Hapi i parë është të krijojmë një repository në Sonatype Maven Central. Për këtë, shkojmë këtu, regjistrohemi dhe krijojmë një detyrë të re, me kërkesën për të krijuar një repository për ne. Shkruajmë GroupId projekti, URL e Projektit linkun për projektin dhe SCM url linkun për sistemin e kontrollit të versioneve, ku ndodhet projekti. GroupId këtu duhet të jetë në formatin com.example, com.example.domain, com.example.testsupport, gjithashtu mund të jetë në formën e një lidhjeje në github-in tuaj: github.com/yourusername -> io.github.yourusername. Në çdo rast, do t'ju kërkohet të konfirmoni pronësinë e këtij domeni ose profili. Nëse keni treguar profilin e github-it, do t'ju kërkojnë të krijoni një repository publik me emrin e nevojshëm.

Pas disa kohësh pas konfirmimit, GroupId juaj do të krijohet dhe mund të kalojmë në hapin tjetër, konfigurimin e Gradle.

Konfigurojmë Gradle

Në momentin e shkruarjes së artikullit, nuk gjetëm plugin për Gradle që mund të ndihmonte me publikimin e artefaktit. Ky plugin-i i vetëm që gjetëm, megjithatë autori e hoqi nga mbështetja e mëtejshme. Prandaj, vendosa ta bëj gjithçka vetë, të cilat nuk ishin shumë të vështira.

E para që duhet të shqyrtojmë janë kërkesat e Sonatype për publikimin. Ato janë si vijon:

  • Prania e kodit burimor dhe JavaDoc, dmth. duhet të jenë të pranishme -sources.jar dhe-javadoc.jar skedarët. Siç thotë dokumentacioni, nëse nuk mund të ofrohet kodi burimor ose dokumentacioni, mund të krijoni një boshllëk -sources.jar ose -javadoc.jar me një README të thjeshtë brenda, për të kaluar verifikimin.
  • Të gjitha skedarët duhet të jenë të nënshkruar me GPG/PGP, dhe .asc skedari që përmban nënshkrimin duhet të përfshihet për çdo skedar.
  • Prania pom skedare
  • Vlerat e sakta groupId, artifactId dhe version. Versioni mund të jetë një varg i rastësishëm dhe nuk mund të përfundojë -SNAPSHOT
  • Prania e emri, description dhe url
  • Prania e informacionit për licencat, zhvilluesit dhe sistemin e kontrollit të versioneve

Këto janë rregullat kryesore që duhet të respektohen gjatë publikimit. Informacioni i plotë është në dispozicion këtu.

Implementojmë këto kërkesa në build.gradle Në fillim, le të shtojmë të gjitha informacionet e nevojshme rreth zhvilluesve, licencës, sistemit të kontrollit të versioneve, si dhe të caktojmë URL-në, emrin dhe përshkrimin e projektit. Për këtë, do të shkruajmë një metodë të thjeshtë:

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

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

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

            description 'Disa përshkrim i artifactit'
            name 'Emri i Artifactit'
            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 'Licenca Apache, 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 'Emri i Zhvilluesit'
                    email 'email@dev.ru'
                }
            }
        }
    }
}

Më pas, duhet të caktojmë që gjatë ndërtimit të gjenerohen -sources.jar dhe-javadoc.jar skedarët. Për këtë, në seksionin java duhet të shtojmë sa vijon:

java {
    withJavadocJar()
    withSourcesJar()
}

Të kalojmë në kërkesën e fundit, konfigurimin e nënshkrimit GPG/PGP. Për këtë do të aktivizojmë add-on-in signing:

plugins {
    id 'signing'
}

Dhe do të shtojmë seksionin:

signing {
    sign publishing.publications
}

Në fund, do të shtojmë seksionin 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 sonatypeUsername dhe sonatypePassword variablat që përmbajnë emrin e përdoruesit dhe fjalëkalimin, të krijuara gjatë regjistrimit në sonatype.org.

Kështu, kodin përfundimtar build.gradle do të duket si më poshtë:

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 'Dëshmi e ndonjë artefakt'
            name 'Emri i artefaktit'
            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 'Licenca Apache, Versioni 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 'Emri i Devit'
                    email 'email@dev.sq'
                }
            }
        }
    }
}

Dua të theksoj se versionin e marrim nga variabla e ambientit: System.getenv('RELEASE_VERSION'). Ne do ta vendosim atë gjatë ndërtimit dhe do ta marrim nga emri i etiketës.

Generimi i çelësit PGP

Një nga kërkesat e Sonatype është nënshkrimi i të gjithë skedareve me çelësin GPG/PGP. Për këtë, shkojmë këtu dhe shkarkojmë mjetin GnuPG për sistemin tonë operativ.

  • Krijojmë një palë çelësash: gpg --gen-key, futim emrin e përdoruesit, e-mailin, dhe përcaktojmë një fjalëkalim.
  • Kërkojmë id çelësin tonë me komandën: gpg --list-secret-keys --keyid-format short. Id do të jetë i shfaqur pas shkronjës, për shembull: rsa2048/9B695056
  • Publikojmë çelësin publik në server https://keys.openpgp.org me komandën: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Eksportojmë çelësin sekret në një vend të rastësishëm, do na nevojitet më vonë: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Konfigurojmë Github Actions

Të kalojmë në hapin përfundimtar, t'i konfigurojmë ndërtimet dhe publikimin automatik, duke përdorur Github Actions.
Github Actions – funksioni që mundëson automatizimin e procesit të punës, duke realizuar ciklin e plotë CI/CD. Ndërtimi, testimi dhe shpërndarja mund të aktivizohen nga ngjarje të ndryshme: shtimi i kodit, krijimi i një versioni ose çështjeve. Ky funksionalitet është krejtësisht falas për depozitat publike.

Në këtë seksion do të tregoj si të konfiguroj ndërtimin dhe shtimin e kodit dhe shpërndarjen në depozitën Sonatype gjatë lëshimit të versionit, si dhe konfigurimin e sekreteve.

Vendosim sekretet

Për ndërtimin automatik dhe shpërndarjen na nevojiten disa vlera sekrete, si id e çelësit, fjalëkalimi që përdorëm gjatë gjenerimit të çelësit, vetë çelësi PGP, si dhe përdoruesi/fjalëkalimi për Sonatype. Ato mund të vendosen në një seksion të veçantë në cilësimet e depozitës:

Përdorim Gradle dhe Github Actions për publikimin e një projekti Java në Sonatype Maven Central Repository

Vendosim variablat e mëposhtme:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD – përdoruesi/fjalëkalimi që përdorëm gjatë regjistrimit në Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD – id e çelësit PGP dhe fjalëkalimi i vendosur gjatë gjenerimit.

Në varg të GPG_KEY_CONTENTS do të ndalem më në detaje. Arsyeja është se për publikimin na nevojitet çelësi privat PGP. Për ta vendosur atë në sekrete, kam përdorur sipërfaqes dhe gjithashtu kam bërë disa veprime të tjera.

  • Do ta enkriptojmë çelësin tonë me gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, duke futur fjalëkalimin. Ai duhet të vendoset në variablin: SECRET_PASSPHRASE
  • Do ta kthejmë çelësin e enkriptuar në një format tekstual duke përdorur base64: base64 9B695056.gpg.gpg > 9B695056.txt. Përmbajtja do të vendoset në variablin: GPG_KEY_CONTENTS.

Konfigurimi i ndërtimit gjatë shtimit të kodit dhe krijimit të PR

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

Në të vendosni një skedë, 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}}

Ky proces do të ekzekutohet gjatë shtimit në degët master, dev dhe testimi, gjithashtu gjatë krijimit të kërkesave të tërheqjes.

Në seksionin jobs janë të renditura hapat që duhet të përfundojnë sipas ngjarjeve të përcaktuara. Në këtë rast do të bëjmë ndërtimin në versionin më të fundit të ubuntu, do të përdorim Java 8, si dhe do të përdorim një plugin për Gradle eskatos/gradle-command-action@v1, i cili duke përdorur versionin më të fundit të ndërtuesit do të ekzekutojë komandat e cekura në arguments. Variablat secrets.SONATYPE_USERNAME dhe secrets.SONATYPE_PASSWORD këto janë sekretet që kemi caktuar më parë.

Rezultatet e ndërtimit do të reflektohen në skedën Actions:

Përdorim Gradle dhe Github Actions për publikimin e një projekti Java në Sonatype Maven Central Repository

Auto-deploy kur lansohet një version i ri

Për autodeploy do të krijojmë një skedar të veçantë të procesit të punës 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ë praktikisht identik me të mëparshmin përveç ngjarjes, kur do të aktivizohet. Në këtë rast, kjo ngjarje është krijimi i një etike te emri që fillon me v.

Para se të bëjmë deploy, na nevojitet të nxjerrim çelësin PGP nga sekretet dhe ta vendosim në rrënjën e projektit, gjithashtu ta dekriptojmë atë. Pastaj, na nevojitet të vendosim një variabël të veçantë mjedisi RELEASE_VERSION në të cilën referohemi në gradle.build skedari. Të gjitha këto bëhen në seksionin Prepare to publish. Ne marrim çelësin tonë nga variabla GPG_KEY_CONTENTS, e kthejmë në skedarin gpg, pastaj e dekriptojmë atë, duke e vendosur në skedarin secret.gpg.

Pastaj ne referohemi në një variabël të veçantë GITHUB_REF, nga e cila mund të nxjerrim versionin që kemi caktuar gjatë krijimit të etiketës. Kjo variablë në këtë rast ka vlerën refs/tags/v0.0.2 nga e cila ne heqim 11 karakteret e para, për të marrë saktësisht versionin. Pastaj përdorim komandat standarde Gradle për publikimin: test publish

Kontrolloni rezultatet e deploy në depoja Sonatype

Pas krijimit të versionit duhet të aktivizohet procesi i punës, i përshkruar në seksionin e mëparshëm. Për këtë krijojmë një version:

Përdorim Gradle dhe Github Actions për publikimin e një projekti Java në Sonatype Maven Central Repository

me emrin e etiketës që duhe të fillojë me v. Nëse pas klikimit të Publish release, procesi i punës përfundon me sukses, ne mund të hyjmë në Sonatype Nexus për të u siguruar për këtë:

Përdorim Gradle dhe Github Actions për publikimin e një projekti Java në Sonatype Maven Central Repository

Artefakti u shfaq në repozitorinë Staging. Ai shfaqet menjëherë me statusin Open, pastaj duhet të transferohet manualisht në statusin Close duke klikuar butonin përkatës. Pas shqyrtimit të përmbushjes së të gjitha kërkesave, artefakti kalon në statusin Close dhe nuk është më i disponueshëm për ndryshime. Në këtë formë ai do të çojë në MavenCentral. Nëse gjithçka është në rregull, mund të klikoni butonin Release, ndërkohë artefakti do të kalojë në repozitorin Sonatype.

Për të siguruar që artefakti të kalojë në MavenCentral, duhet të kërkoni këtë në detyrën që krijuam në fillim. Kjo duhet bërë vetëm një herë, sepse ne po publikojmë për herë të parë. Herët e tjera nuk është e nevojshme, gjithçka do të sinkronizohet automatikisht. Më shkurt aktivizuan sinkronizimin për mua, por që artefakti të bëhet i disponueshëm në MavenCentral kaloi rreth 5 ditë.

Këtu përfundon, ne publikojmë artefaktin tonë në MavenCentral.

Useful links

  • E ngjashme artikulli, vetëm publikimi përmes maven
  • Staging repozitori Sonatype
  • Jira Sonatype, ku është e nevojshme të krijohet një detyrë
  • Shembulli repozitore, ku gjithçka është e konfiguruar

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster