Izmantojam Gradle un Github Actions, lai publicētu Java projektu Sonatype Maven Central Repository

Šajā rakstā es gribu detalizēti apskatīt Java artefakta publicēšanas procesu no nulles, izmantojot Github Actions Sonatype Maven Central Repository ar Gradle būvētāju.

Šo rakstu nolēmu uzrakstīt, ņemot vērā normāla pamācības trūkumu vienā vietā. Visiem pieejamajiem informācijas fragmentiem nācās tikt savāktiem no dažādiem avotiem, turklāt ne visai svaigiem. Kam interesē, laipni lūdzam zemāk.

Repotārija izveide Sonatype

Pirmajā posmā mums jāizveido repotārijs Sonatype Maven Central. Tādēļ dodamies šeit, reģistrējamies un izveidojam jaunu uzdevumu, lūdzot izveidot mums repotāriju. Ievadām savu GroupId projekta, Projekta URL projekta saiti un SCM url saiti uz versiju kontroles sistēmu, kurā atrodas projekts. GroupId šim jābūt formātā com.example, com.example.domain, com.example.testsupport, kā arī var būt jūsu Github saite: github.com/yourusername -> io.github.yourusername. Jebkurā gadījumā jums būs jāapstiprina šī domēna vai profila īpašumtiesības. Ja norādījāt Github profilu, tiks lūgts izveidot publisku repotāriju ar nepieciešamo nosaukumu.

Pēc kāda laika pēc apstiprināšanas jūsu GroupId tiks izveidots, un mēs varam pāriet uz nākamo soli, Gradle konfigurāciju.

Konfigurējam Gradle

Raksta rakstīšanas brīdī es neatradu Gradle spraudņus, kas varētu palīdzēt publicēšanas procesā. Tas ir vienīgais spraudnis, ko es atradu, bet autora atsakās no turpmākās atbalsta. Tādēļ es nolēmu visu izdarīt pats, jo to izdarīt nav tik grūti.

Pirmais, kas jānoskaidro, ir Sonatype pieprasījumi publicēšanai. Tie ir sekojoši:

  • Būtiski ir nodrošināt avota kodus un JavaDoc, t.i., jābūt pieejamiem -sources.jar un-javadoc.jar failiem. Kā minēts dokumentācijā, ja nav iespējams nodrošināt avota kodus vai dokumentāciju, var izveidot tukšu failu -sources.jar vai -javadoc.jar ar vienkāršu README iekšā, lai izietu pārbaudi.
  • Visiem failiem jābūt parakstītiem ar GPG/PGP, un .asc fails, kas satur parakstu, jākļūst iekļautam katrā failā.
  • Nodrošina pom faila
  • Korekti vērtības groupId, artifactId un version. Versijai var būt jebkāda virkne, un tai nedrīkst beigties -SNAPSHOT
  • Nepieciešama name, apraksts un url
  • Informācijai par licencēm, izstrādātājiem un versiju kontroles sistēmu

Šie ir galvenie noteikumi, kas jāievēro publicēšanas procesā. Pilna informācija ir pieejama šeit.

Ieviešam šos pieprasījumus build.gradle failā. Lai sāktu, pievienosim visu nepieciešamo informāciju par izstrādātājiem, licenci, versiju kontroli, kā arī norādīsim URL, nosaukumu un projekta aprakstu. Tādēļ uzrakstīsim vienkāršu metodi:

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

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

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

            description 'Kāds artefakta apraksts'
            name 'Artefakta nosaukums'
            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 '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.lv'
                }
            }
        }
    }
}

Tālāk jānorāda, ka būvēšanas laikā nepieciešams ģenerēt -sources.jar un-javadoc.jar failus. Tādēļ sadaļā java jāievada sekojošais:

java {
    withJavadocJar()
    withSourcesJar()
}

Pāriesim pie pēdējā prasība, GPG/PGP paraksta konfigurācija. Tādēļ pievienosim spraudni signing:

plugins {
    id 'signing'
}

Un pievienosim sadaļu:

signing {
    sign publishing.publications
}

Visbeidzot, pievienosim sadaļu 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
            }
        }
    }
}

Šeit sonatypeUsername un sonatypePassword mainīnes, kas satur lietotājvārdu un paroli, izveidotās reģistrējoties sonatype.org.

Tādējādi, galīgais build.gradle izskatīsies šādi:

Pilns kods 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.lv'
                }
            }
        }
    }
}

Vēlos piebilst, ka versiju iegūstam no vides mainīgā: System.getenv('RELEASE_VERSION'). Mēs to iestatīsim būvēšanas procesā un ņemsim no taga nosaukuma.

PGP atslēgas ģenerēšana

Viens no Sonatype prasībām ir visu failu parakstīšana, izmantojot GPG/PGP atslēgu. Tāpēc dodamies šeit un lejupielādējam GnuPG utilītu savai operētājsistēmai.

  • Ģenerējam atslēgu pāri: gpg --gen-key, ievadām lietotāja vārdu, e-pastu un nosakām paroli.
  • Noskaidrojam id mūsu atslēgas ar komandu: gpg --list-secret-keys --keyid-format short. Id tiks norādīts pēc slīpsvītras, piemēram: rsa2048/9B695056
  • Publicējam publisko atslēgu uz serveri https://keys.openpgp.org ar komandu: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Eksportējam slepeno atslēgu uz jebkuru vietu, tā mums noderēs nākotnē: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Iestatām Github Actions

Pārejam uz noslēguma posmu, iestatīsim būvēšanu un automātisko publikāciju, izmantojot Github Actions.
Github Actions – funkcionalitāte, kas ļauj automatizēt darba procesus, realizējot pilnu CI/CD ciklu. Kompilācija, testēšana un izvietošana var tikt izsauktas ar dažādiem notikumiem: koda nosūtīšana, laidiena vai problēmu izveide. Šī funkcionalitāte ir pilnīgi bez maksas publiskajiem repozitorijiem.

Šajā sadaļā es parādīšu, kā iestatīt kompilāciju un koda nosūtīšanu, kā arī izvietošanu Sonatype repozitorijā, kad tiek laists klajā laidienu, un kā iestatīt slepenos datus.

Iestādām slepenos datus

Automātiskai kompilācijai un izvietošanai mums būs nepieciešami vairāki slepenie vērtības, piemēram, atslēgas ID, parole, kuru mēs ievadījām, ģenerējot atslēgu, pati PGP atslēga, kā arī lietotājvārds/parole uz Sonatype. Tos var iestatīt īpašā sadaļā repozitorija iestatījumos:

Izmantojam Gradle un Github Actions, lai publicētu Java projektu Sonatype Maven Central Repository

Iestādām šādas mainīgās:

  • SONATYPE_USERNAME/SONATYPE_PASSWORD — lietotājvārds/parole, kuru mēs ievadījām reģistrējoties Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — PGP atslēgas ID un parole, kas iestatīta tās ģenerēšanas brīdī.

Par mainīgo GPG_KEY_CONTENTS vēlos apstāties sīkāk. Proti, mums publicēšanai nepieciešama privātā PGP atslēga. Lai to ievietotu slepenajos datus, es izmantoju norādījumus un papildus veicu vairākus pasākumus.

  • Iezīmēsim mūsu atslēgu, izmantojot gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpg, ievadot paroli. To vajadzētu ievietot mainīgajā: SECRET_PASSPHRASE
  • Pārvērsīsim iegūto šifrēto atslēgu tekstveidīgā formātā, izmantojot base64: base64 9B695056.gpg.gpg > 9B695056.txt. Saturu izvietosim mainīgajā: GPG_KEY_CONTENTS.

Iestatīšana kompilācijai, nosūtot kodu un veidojot PR

Vispirms jāizveido mape jūsu projekta saknē: .github/workflows.

Tajā jānovieto fails, piemēram, gradle-ci-build.yml ar sekojošo saturu:

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

Šis darba process tiks izpildīts, nosūtot uz zariem master, dev un testing, kā arī veidojot pull pieprasījumus.

Jobs sadaļā ir norādīti soļi, kas jāveic, ņemot vērā minētās izvēlētās darbības. Šajā gadījumā mēs kompilēsim uz jaunākās ubuntu versijas, izmantosim Java 8 un speciālo spraudni Gradle eskatos/gradle-command-action@v1, kas, izmantojot jaunāko versiju, palaiž komandas, kas norādītas arguments. Mainīgās secrets.SONATYPE_USERNAME un secrets.SONATYPE_PASSWORD tie ir noslēpumi, kurus mēs iepriekš iestatījām.

Veiksmīgā būvē rezultāti tiks atspoguļoti cilnē Actions:

Izmantojam Gradle un Github Actions, lai publicētu Java projektu Sonatype Maven Central Repository

Automātiska izvietošana jaunā laidiena izdošanas laikā

Automātiskai izvietošana izveidosim atsevišķu darba procesa failu gradle-ci-publish.yml:

name: publish

on:
  push:
    tags:
      - 'v*'

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Iestatīt JDK 8
        uses: actions/setup-java@v1
        with:
          java-version: 8

      - name: Sagatavot publikācijai
        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: Publikācija ar 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}}

Fails praktiski ir identisks iepriekšējam, izņemot notikumu, kad tas tiks izpildīts. Šajā gadījumā tas ir notikums, kad tiek izveidots tag, kura nosaukums sākas ar v.

Pirms izvietošanas mums ir jāņem PGP atslēga no noslēpumiem un jānovieto to projekta saknē, kā arī jāatšifrē. Turpmāk mums ir jāiestata īpaša vides mainīgā RELEASE_VERSION , kuru mēs izmantojam gradle.build failā. Viss šis process tiek veikts sadaļā Sagatavot publikācijai. Mēs iegūstam mūsu atslēgu no maiņīgā GPG_KEY_CONTENTS, pārvēršam to gpg failā, pēc tam to atšifrējam, ievietojot failā secret.gpg.

Tālāk mēs piekļūstam īpašajai maiņīgajai GITHUB_REF, no kuras varam iegūt versiju, kuru mēs iestatījām, izveidojot tagu. Šai maiņīgajai šajā gadījumā ir vērtība refs/tags/v0.0.2 , no kuras mēs noņemam pirmos 11 simbolus, lai iegūtu tieši versiju. Pēc tam standartā izmantojam Gradle komandas publikācijai: test publish

Pārbaudīt rezultātus izvietošanai Sonatype krātuvē

Pēc laidiena izveidošanas vajadzētu uzsākt darba procesu, kas aprakstīts iepriekšējā sadaļā. Lai to izdarītu, izveidojam laidienu:

Izmantojam Gradle un Github Actions, lai publicētu Java projektu Sonatype Maven Central Repository

šajā gadījumā tagam jāuzsākas ar v. Ja pēc Publish release nospiešanas darba process veiksmīgi noslēdzas, mēs varam doties uz Sonatype Nexus , lai to pārliecinātos:

Izmantojam Gradle un Github Actions, lai publicētu Java projektu Sonatype Maven Central Repository

Artifacts aparecās Staging repozitorijā. Tas sākotnēji parādās ar statusu Open, pēc tam to manuāli jāmaina uz statusu Close, nospiežot attiecīgo pogu. Pēc visu prasību izpildes pārbaudes artifacts tiek pārvērsts statusā Close un vairs nav pieejams izmaiņām. Šādā formā tas nonāks MavenCentral. Ja viss ir labi, varat nospiest pogu Izlaidums, šajā gadījumā artifacts nonāks Sonatype repozitorijā.

Lai artifacts nonāktu MavenCentral, ir jāpiesakās tam uz uzdevumu, kuru mēs izveidojām sākumā. Tas jādara tikai vienu reizi, jo mēs publicējam to pirmo reizi. Nākamajās reizēs tas nav nepieciešams, viss tiks sinhronizēts automātiski. Sinhronizācija tika ieslēgta ātri, taču, lai artifacts kļūtu pieejams MavenCentral, pagāja apmēram 5 dienas.

Šeit viss ir paveikts, mēs esam publicējuši savu artifact MavenCentral.

Noderīgas saites

  • Līdzīgs raksts, tikai publicēšana caur maven
  • Staging repozitorijs Sonatype
  • Jira Sonatype, kurā ir jāizveido uzdevums
  • uzbrukumam repozitorijā, kur viss ir iestatīts

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster