„Gradle“ ir „Github“ veiksmų naudojimas „Java“ projektui paskelbti „Sonatype Maven“ centrinėje saugykloje

Šiame straipsnyje noriu išsamiai apžvelgti „Java“ artefakto publikavimo procesą nuo nulio iki „Github Actions“ iki „Sonatype Maven“ centrinės saugyklos naudojant „Gradle“ kūrimo priemonę.

Nusprendžiau parašyti šį straipsnį, nes vienoje vietoje trūko įprastos pamokos. Visą informaciją reikėjo rinkti po gabalėlį iš įvairių šaltinių, be to, ne visai šviežią. Kam rūpi, sveiki atvykę po katinu.

Saugyklos kūrimas „Sonatype“.

Pirmasis žingsnis yra sukurti saugyklą Sonatype Maven Central. Dėl to einame čia, užsiregistruokite ir sukurkite naują užduotį, prašydami mūsų sukurti saugyklą. Važiuojame savo Grupės ID projektas, Projekto URL projekto nuoroda ir SCM url nuoroda į versijų valdymo sistemą, kurioje yra projektas. Grupės ID čia turėtų būti com.example, com.example.domain, com.example.testsupport, taip pat gali būti nuoroda į jūsų github: github.com/yourusername -> io.github.yourusername. Bet kokiu atveju turėsite patvirtinti šio domeno ar profilio nuosavybės teisę. Jei nurodėte „github“ profilį, jūsų bus paprašyta sukurti viešą saugyklą norimu pavadinimu.

Praėjus šiek tiek laiko po patvirtinimo, jūsų grupės ID bus sukurtas ir galėsime pereiti prie kito veiksmo – „Gradle“ konfigūravimo.

„Gradle“ konfigūravimas

Rašymo metu neradau „Gradle“ papildinių, kurie galėtų padėti paskelbti artefaktą. Jis vienintelis įskiepis, kurį radau, tačiau autorius atsisakė toliau jį palaikyti. Todėl nusprendžiau viską daryti pats, nes tai padaryti nėra labai sunku.

Pirmas dalykas, kurį reikia išsiaiškinti, yra „Sonatype“ reikalavimai leidybai. Jie yra šie:

  • Šaltinio kodų ir JavaDoc prieinamumas, ty. privalo dalyvauti -sources.jar и-javadoc.jar failus. Kaip nurodyta dokumentacijoje, jei neįmanoma pateikti šaltinio kodų ar dokumentų, galite padaryti manekeną -sources.jar arba -javadoc.jar su paprastu README viduje, kad išlaikytumėte testą.
  • Visi failai turi būti pasirašyti GPG/PGPIr .asc prie kiekvieno failo turi būti įtrauktas failas su parašu.
  • Prieinamumas pom failą
  • Teisingos vertės groupId, artifactId и version. Versija gali būti savavališka eilutė ir negali baigtis -SNAPSHOT
  • Reikalingas buvimas name, description и url
  • Informacijos apie licenciją, kūrėjus ir versijų valdymo sistemą buvimas

Tai yra pagrindinės taisyklės, kurių privalu laikytis skelbiant. Yra visa informacija čia.

Šiuos reikalavimus įgyvendiname build.gradle failą. Pirmiausia pridėkime visą reikiamą informaciją apie kūrėjus, licencijas, versijų valdymo sistemą, taip pat nustatykime projekto URL, pavadinimą ir aprašymą. Parašykime paprastą metodą:

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

Tada turite tai nurodyti sugeneruoto surinkimo metu -sources.jar и-javadoc.jar failus. Šiam skyriui java reikia pridėti šiuos dalykus:

java {
    withJavadocJar()
    withSourcesJar()
}

Pereikime prie paskutinio reikalavimo – GPG/PGP parašo nustatymo. Norėdami tai padaryti, prijunkite priedą signing:

plugins {
    id 'signing'
}

Ir pridėkite skyrių:

signing {
    sign publishing.publications
}

Galiausiai pridėkime skyrių 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
            }
        }
    }
}

Čia sonatype Vartotojo vardas и sonatypePassword kintamieji, kuriuose yra prisijungimo vardas ir slaptažodis, sukurti registracijos metu sonatype.org.

Taigi finalas build.gradle atrodys taip:

Visas build.gradle kodas

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

Noriu pažymėti, kad versiją gauname iš aplinkos kintamojo: System.getenv('RELEASE_VERSION'). Mes jį atskleisime surinkimo metu ir paimsime iš žymos pavadinimo.

PGP raktų generavimas

Vienas iš Sonatype reikalavimų yra tas, kad visi failai būtų pasirašyti GPG/PGP raktu. Dėl to einame čia ir atsisiųskite savo operacinei sistemai skirtą GnuPG priemonę.

  • Sukuriame raktų porą: gpg --gen-key, įveskite vartotojo vardą, el. pašto adresą ir taip pat nustatykite slaptažodį.
  • Sužinome id mūsų raktas su komanda: gpg --list-secret-keys --keyid-format short. ID bus nurodytas po pasvirojo brūkšnio, pavyzdžiui: rsa2048/9B695056
  • Viešojo rakto paskelbimas serveryje https://keys.openpgp.org pagal komandą: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Slaptąjį raktą eksportuojame į savavališką vietą, jo mums prireiks ateityje: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

„Github“ veiksmų nustatymas

Pereikime prie paskutinio etapo, nustatykite kūrimą ir automatiškai paskelbkite naudodami „Github Actions“.
„Github Actions“ yra funkcija, leidžianti automatizuoti darbo eigą įgyvendinant visą CI / CD ciklą. Sukūrimą, testavimą ir diegimą gali suaktyvinti įvairūs įvykiai: kodo siuntimas, leidimo kūrimas ar problemos. Ši funkcija yra visiškai nemokama viešosioms saugykloms.

Šiame skyriuje parodysiu, kaip nustatyti kūrimo ir siuntimo kodą ir įdiegti į Sonatype saugyklą išleidus, taip pat nustatyti paslaptis.

Mes nustatome paslaptis

Automatiniam surinkimui ir diegimui mums reikia kelių slaptų reikšmių, tokių kaip rakto ID, slaptažodis, kurį įvedėme generuodami raktą, pats PGP raktas ir Sonatype prisijungimo/slaptažodis. Galite juos nustatyti specialioje saugyklos nustatymų skiltyje:

„Gradle“ ir „Github“ veiksmų naudojimas „Java“ projektui paskelbti „Sonatype Maven“ centrinėje saugykloje

Mes nustatome šiuos kintamuosius:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD – prisijungimo vardas / slaptažodis, kurį įvedėme registruodamiesi „Sonatype“
  • SIGNING_KEYID/SIGNING_PASSWORD – generuojant nustatytas PGP rakto ID ir slaptažodis.

Noriu pasilikti prie kintamojo GPG_KEY_CONTENTS išsamiau. Faktas yra tas, kad publikavimui mums reikia privataus PGP rakto. Norėdamas paskelbti jį paslaptyse, aš naudojau instrukcija ir papildomai atliko keletą veiksmų.

  • Užšifruokime savo raktą su gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgįvesdami slaptažodį. Jis turėtų būti įdėtas į kintamąjį: SECRET_PASSPHRASE
  • Išverskime gautą užšifruotą raktą į tekstinę formą naudodami base64: base64 9B695056.gpg.gpg > 9B695056.txt. Turinys bus patalpintas į kintamąjį: GPG_KEY_CONTENTS.

Sukurkite sąranką stumdami kodą ir kurdami PR

Pirmiausia turite sukurti aplanką savo projekto šaknyje: .github/workflows.

Jame pažymėkite failą, pavyzdžiui, gradle-ci-build.yml su tokiu turiniu:

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

Ši darbo eiga bus vykdoma stumiant į šakas master, dev и testing, taip pat kuriant ištraukimo užklausas.

Užduočių skiltyje nurodomi veiksmai, kurie turi būti atlikti su nurodytais įvykiais. Tokiu atveju mes remsimės naujausia ubuntu versija, naudosime Java 8, taip pat naudosime Gradle įskiepį eskatos/gradle-command-action@v1kuri, naudojant naujausią kūrimo priemonės versiją, vykdys komandas, nurodytas arguments. Kintamieji secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD tai paslaptys, kurių klausėme anksčiau.

Kūrimo rezultatai bus rodomi skirtuke Veiksmai:

„Gradle“ ir „Github“ veiksmų naudojimas „Java“ projektui paskelbti „Sonatype Maven“ centrinėje saugykloje

Automatinis diegimas, kai išleidžiamas naujas leidimas

Sukurkime atskirą darbo eigos failą automatiniam diegimui 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}}

Failas yra beveik identiškas ankstesniam, išskyrus įvykį, kurio metu jis bus suaktyvintas. Šiuo atveju tai yra žymos su pavadinimu, prasidedančiu raide v, sukūrimo įvykis.

Prieš diegdami turime išgauti PGP raktą iš paslapčių ir įdėti jį į projekto šaknį, taip pat iššifruoti. Tada turime nustatyti specialų aplinkos kintamąjį RELEASE_VERSION kuria mes remiamės gradle.build failą. Visa tai daroma skyriuje Prepare to publish. Mes gauname raktą iš kintamojo GPG_KEY_CONTENTS, išverčiame jį į gpg failą, tada iššifruojame įdėdami į failą secret.gpg.

Toliau kreipiamės į specialų kintamąjį GITHUB_REF, iš kurio galime gauti versiją, kurią nustatėme kurdami žymą. Šis kintamasis yra svarbus šiuo atveju. refs/tags/v0.0.2 iš kurių nupjauname pirmuosius 11 simbolių, kad gautume konkrečią versiją. Tada publikavimui naudojame standartines Gradle komandas: test publish

Tikrinami diegimo rezultatai „Sonatype“ saugykloje

Sukūrus leidimą, turėtų prasidėti ankstesniame skyriuje aprašyta darbo eiga. Norėdami tai padaryti, sukurkite leidimą:

„Gradle“ ir „Github“ veiksmų naudojimas „Java“ projektui paskelbti „Sonatype Maven“ centrinėje saugykloje

žymos pavadinimas turi prasidėti raide v. Jei spustelėjus Paskelbti leidimą darbo eiga sėkmingai baigta, galime pereiti prie „Sonatype Nexus“ įsitikinti:

„Gradle“ ir „Github“ veiksmų naudojimas „Java“ projektui paskelbti „Sonatype Maven“ centrinėje saugykloje

Artefaktas pasirodė „Stage“ saugykloje. Jis iš karto pasirodo „Open“ būsenoje, tada jį reikia rankiniu būdu perkelti į „Close“ būseną, paspaudus atitinkamą mygtuką. Patikrinus, ar tenkinami visi reikalavimai, artefaktas pereina į būseną Uždaryti ir jo nebegalima keisti. Šioje formoje jis pateks į MavenCentral. Jei viskas gerai, galite paspausti mygtuką Atleiskite, ir artefaktas pateks į Sonatype saugyklą.

Kad artefaktas patektų į MavenCentral, turite jo paprašyti užduotyje, kurią sukūrėme pačioje pradžioje. Tai padaryti reikia tik vieną kartą, todėl skelbiame pirmą kartą. Vėlesniais laikais to nereikia, viskas bus sinchronizuojama automatiškai. Jie man greitai įjungė sinchronizavimą, bet prireikė maždaug 5 dienų, kol artefaktas buvo pasiekiamas MavenCentral.

Tai viskas, mes paskelbėme savo artefaktą MavenCentral.

Naudingos nuorodos

  • Panašus straipsnis, skelbti tik per maven
  • Pastatymas saugykla Sonatipas
  • JIRA Sonatipas, kuriame reikia sukurti užduotį
  • Pavyzdys saugykla, kurioje viskas nustatyta

Šaltinis: www.habr.com