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

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

Vendosa ta shkruaj këtë artikull për shkak të mungesës së një tutoriali normal në një vend. Informacionin e duhur e kam mbledhur në copa nga burime të ndryshme, të cilat nuk ishin gjithmonë të freskëta. Ata që janë të interesuar, mirëseerdhët nën kat.

Krijimi i repositorit në Sonatype

Hapi i parë është të krijojmë një repozitor në Sonatype Maven Central. Për këtë shkojmë . Kërkesat e dërguara përmes mënyrave të tjera nuk do të shqyrtohen., regjistrohemi dhe krijojmë një detyrë të re, duke kërkuar të na krijohet një repozitor. Shkruajmë GroupId i projektit, URL-në e Projektit linkun për projektin dhe SCM url linkun për sistemin e kontrollit të versioneve, në të cilin ndodhet projekti. GroupId këtu duhet të jetë në formën com.example, com.example.domain, com.example.testsupport, ose mund të jetë në formën e një linku për 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 cituar profilin e Github-it, do t'ju kërkohet të krijoni një repozitor publik me emrin përkatës.

Pas një kohe pas konfirmimit, GroupId juaj do të krijohet dhe ne mund të kalojmë në hapin e ardhshëm, konfigurimin e Gradle.

Konfigurojmë Gradle

Në momentin që po shkruaj këtë artikull, nuk kam gjetur plugin për Gradle që mund të ndihmojë në publikimin e artefaktit. Kjo plugin-i i vetëm që kam gjetur, por autori është tërhequr nga mbështetje e tij. Prandaj, vendosa ta bëj gjithçka vetë, duke patur parasysh se nuk është shumë e vështirë.

E para që duhet të zbulojmë, janë kërkesat e Sonatype për publikim. Ato janë si në vijim:

  • Prania e kodit burimor dhe JavaDoc, dmth. duhet tĂ« jenĂ« tĂ« pranishme -sources.jar dhe-javadoc.jar skedarĂ«t. Ashtu siç thuhet nĂ« dokumentacion, nĂ«se nuk Ă«shtĂ« e mundur tĂ« ofrohen kodet burimore ose dokumentacioni, mund tĂ« krijoni njĂ« skedar tĂ« zbrazĂ«t -sources.jar ose -javadoc.jar me njĂ« README tĂ« thjeshtĂ« brenda, pĂ«r tĂ« kaluar verifikimin.
  • TĂ« gjitha skedarĂ«t duhet tĂ« nĂ«nshkruhen me GPG/PGP, dhe .asc skedari pĂ«rmban nĂ«nshkrimin, duhet tĂ« pĂ«rfshihet pĂ«r çdo skedar.
  • Prania pom e skedarit
  • Vlerat e sakta groupId, artifactId dhe version. Versioni mund tĂ« jetĂ« njĂ« varg i rastĂ«sishĂ«m dhe nuk mund tĂ« pĂ«rfundojĂ« -SNAPSHOT
  • Nevojitet tĂ« ketĂ« emri, description dhe url
  • Prania e informacionit mbi 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.

Realizojmë këto kërkesa në build.gradle skedari. Fillimisht, le të shtojmë të gjitha informacionet e nevojshme për zhvilluesit, licencat, sistemin e kontrollit të versioneve, si dhe të caktojmë URL-në, emrin dhe përshkrimin e projektit. Për këtë, shkruajmë një metoda 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 artefaktit'
            name 'Emri i Artefaktit'
            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ë tregojmë se gjatë ndërtimit të krijohen -sources.jar dhe-javadoc.jar skedarët. Për këtë, në seksionin java duhet të shtojmë të mirat:

java {
    withJavadocJar()
    withSourcesJar()
}

Të kalojmë në kërkesën e fundit, konfigurimin e nënshkrimit GPG/PGP. Për këtë, do të lidhim plugin-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 dhe fjalëkalimin, të krijuara gjatë regjistrimit në sonatype.org.

Kështu, kodi 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 'Disa se e artefaktit'
            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, 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 'Emri i Dev'
                    email 'email@dev.ru'
                }
            }
        }
    }
}

Dua të theksoj se versionin e marrim nga variabla e ambientit: System.getenv('RELEASE_VERSION'). Do ta vendosim 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ë gjitha skedarëve me çelësin GPG/PGP. Për këtë, shkojmë . Kërkesat e dërguara përmes mënyrave të tjera nuk do të shqyrtohen. dhe shkarkojmë utilitarin GnuPG për sistemin e operimit të vet.

  • NdĂ«rtojmĂ« çift çelĂ«sash: gpg --gen-key, shkruajmĂ« emrin e pĂ«rdoruesit, e-mail-in, dhe vendosim njĂ« fjalĂ«kalim.
  • Zbuloni id çelĂ«sin tonĂ« me komandĂ«n: gpg --list-secret-keys --keyid-format short. Id-ja do tĂ« jetĂ« e shĂ«nuar pas shkronjĂ«s, pĂ«r shembull: rsa2048/9B695056
  • Publikoni çelĂ«sin publik nĂ« server https://keys.openpgp.org komandĂ«n: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Eksportoni çelĂ«sin sekret nĂ« njĂ« vend tĂ« rastĂ«sishĂ«m, do na nevojitet mĂ« vonĂ«: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Konfiguroni Github Actions

Tani do të kalojmë në fazën përfundimtare, do të konfigurojmë ndërtimin dhe publikimin automatik, duke përdorur Github Actions.
Github Actions – funksionaliteti qĂ« lejon automatizimin e procesit tĂ« punĂ«s, duke realizuar njĂ« cikĂ«l tĂ« plotĂ« CI/CD. NdĂ«rtimi, testimi dhe publikimi mund tĂ« thirren nga ngjarje tĂ« ndryshme: shtimi i kodit, krijimi i lĂ«shimit ose çështjeve. Ky funksionalitet Ă«shtĂ« plotĂ«sisht falas pĂ«r repo publik.

Në këtë seksion do të tregoj si të konfiguroj ndërtimin dhe shtimin e kodit dhe publikimin në repo Sonatype gjatë nxjerrjes së lëshimit, si dhe konfigurimin e sekreteve.

Caktoni sekretet

PĂ«r ndĂ«rtimin dhe publikimin automatik, na nevojiten njĂ« sĂ«rĂ« vlerash sekrete, si id e çelĂ«sit, fjalĂ«kalimi qĂ« vendosĂ«m gjatĂ« ndĂ«rtimit tĂ« çelĂ«sit, çelĂ«si PGP vetĂ« dhe gjithashtu login/fjalĂ«kalimi pĂ«r Sonatype. Mund t’i caktoni ato nĂ« njĂ« seksion tĂ« veçantĂ« nĂ« cilĂ«simet e repo:

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

Caktoni variablat e mëposhtme:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD — login/fjalĂ«kalimi qĂ« ne vendosĂ«m gjatĂ« regjistrimit nĂ« Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — id e çelĂ«sit PGP dhe fjalĂ«kalimi i vendosur gjatĂ« gjenerimit.

Dua të ndalem pak më gjatë te variabla GPG_KEY_CONTENTS. E vërteta është se për publikim na nevojitet çelësi i mbyllur PGP. Për ta vendosur në sekrete, unë përdora udhezimin dhe realizova edhe një sërë veprimesh.

  • Do tĂ« enkriptoj çelĂ«sin tonĂ« me gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, duke vendosur njĂ« fjalĂ«kalim. Kjo duhet tĂ« vendoset nĂ« variablĂ«n: SECRET_PASSPHRASE
  • Do ta konvertojmĂ« çelĂ«sin e enkriptuar nĂ« format tekstual me base64: base64 9B695056.gpg.gpg > 9B695056.txt. PĂ«rmbajtja do tĂ« vendoset nĂ« variablĂ«n: GPG_KEY_CONTENTS.

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

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

Brenda saj vendosni një skedar, 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 pune do të ekzekutohet gjatë shtimit në degët master, dev dhe testing, gjithashtu gjatë krijimit të kërkesave të tërheqjes.

Në seksionin jobs janë hapat që duhet të realizohen për ngjarjet e specifikuara. Në këtë rast do të ndërtojmë në versionin më të fundit të ubuntu, do të përdorim Java 8, si dhe doemos plugin-in 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 shënuara në argumente. Variablat secrets.SONATYPE_USERNAME dhe secrets.SONATYPE_PASSWORD këto janë sekrete që kemi vendosur më parë.

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

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

Autodeploy gjatë lëshimit të një versioni të ri

Për autodeploy do të krijojmë një skedë të veçantë punë 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}}

Skeda është pothuajse identike me atë të mëparshmen, përveç ngjarjes kur do të aktivizohet. Në këtë rast, kjo është ngjarja e krijimit të një etikete me emrin që fillon me v.

Para se të bëjmë deploy, na nevojitet të nxjerrim çelësin PGP nga sekretet dhe ta vendosim atë në rrënjën e projektit, si dhe ta dekriptojmë atë. Pastaj na nevojitet të vendosim një ndryshore të veçantë ambienti RELEASE_VERSION për të cilën referohemi në gradle.build skedë. Të gjitha këto janë kryer në seksionin Prepare to publish. Ne nxjerrim çelësin tonë nga variabla GPG_KEY_CONTENTS, e transformojmë atë në skedën gpg, pastaj e dekriptojmë, duke e vendosur në skedën secret.gpg.

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

Kontrolli i rezultateve të deploy-it në repository-në Sonatype

Pas krijimit të versionit, duhet të fillojë 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 projektit Java në Sonatype Maven Central Repository

duke bërë që emri i etiketës 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 ta verifikuar këtë:

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

Arti-fakti u shfaq në repository-në Staging. Ai fillimisht shfaqet me statusin Open, pastaj duhet ta kalosh dorazi në statusin Close, duke klikuar në butonin përkatës. Pas kontrollit të përmbushjes së të gjitha kërkesave, arti-fakti kalon në statusin Close dhe nuk është më i aksesueshëm për ndryshime. Në këtë formë, ai do të përfundojë në MavenCentral. Nëse gjithçka është në rregull, mund të klikoni butonin Release, në këtë rast arti-fakti do të kalojë në repository-në Sonatype.

Për të siguruar që arti-fakti të përfundojë në MavenCentral, duhet të kërkoni këtë në detyrën që krijuam në fillim. Kjo duhet të bëhet vetëm një herë, pasi po publikojmë për herë të parë. Herët e tjera, kjo nuk është e nevojshme; gjithçka do të sinkronizohet automatikisht. Më aktivizuan sinkronizimin shpejt, por që arti-fakti të bëhet i aksesueshëm në MavenCentral kaluan rreth 5 ditë.

Këtu është mbyllur, kemi publikuar arti-faktin tonë në MavenCentral.

Linqe të dobishme

  • NjĂ« ngjashmĂ«ri artikull, vetĂ«m publikimi pĂ«rmes maven
  • Staging repo Sonatype
  • Jira Sonatype, nĂ« tĂ« cilĂ«n duhet tĂ« krijoni njĂ« detyrĂ«
  • Shembuj repository, ku Ă«shtĂ« e gjithçka e konfiguruar

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster