Gradle- ja Github-toimintojen käyttäminen Java-projektin julkaisemiseen Sonatype Maven Central Repositoryssa

Tässä artikkelissa haluan tarkastella lähemmin Java-artefaktin julkaisuprosessia tyhjästä Github Actionsin kautta Sonatype Maven Central Repositoryyn käyttämällä Gradle-rakennusohjelmaa.

Päätin kirjoittaa tämän artikkelin, koska normaalia opetusohjelmaa ei ollut yhdessä paikassa. Kaikki tieto piti kerätä pala kerrallaan eri lähteistä, ei myöskään täysin tuoretta. Ketä kiinnostaa, tervetuloa kissan alle.

Arkiston luominen Sonatypessä

Ensimmäinen askel on luoda arkisto Sonatype Maven Centralissa. Tätä varten mennään täällä, rekisteröidy ja luo uusi tehtävä pyytäen meitä luomaan arkiston. Me ajamme omassamme Ryhmätunnus projekti, Projektin URL-osoite projekti linkki ja SCM url linkki versionhallintajärjestelmään, jossa projekti sijaitsee. Ryhmätunnus tämän pitäisi olla muotoa com.example, com.example.domain, com.example.testsupport, ja se voi olla myös linkin muodossa githubiisi: github.com/käyttäjänimesi -> io.github.käyttäjänimesi. Joka tapauksessa sinun on vahvistettava tämän verkkotunnuksen tai profiilin omistajuus. Jos määritit github-profiilin, sinua pyydetään luomaan julkinen arkisto halutulla nimellä.

Jonkin ajan kuluttua vahvistuksen jälkeen GroupId luodaan ja voimme siirtyä seuraavaan vaiheeseen, Gradle-määritykseen.

Gradlen määrittäminen

Tätä kirjoittaessani en löytänyt Gradle-laajennuksia, jotka voisivat auttaa artefaktin julkaisemisessa. Se Ainoa löytämäni laajennus, mutta kirjoittaja kieltäytyi tukemasta sitä enempää. Siksi päätin tehdä kaiken itse, koska sen tekeminen ei ole liian vaikeaa.

Ensimmäinen asia, joka on selvitettävä, on Sonatypen julkaisuvaatimukset. Ne ovat seuraavat:

  • Lähdekoodien ja JavaDocin saatavuus, esim. täytyy osallistua -sources.jar и-javadoc.jar tiedostot. Kuten dokumentaatiossa todetaan, jos lähdekoodeja tai dokumentaatiota ei ole mahdollista toimittaa, voit tehdä nuken -sources.jar tai -javadoc.jar yksinkertaisella README-komennolla testin läpäisemiseksi.
  • Kaikki tiedostot on allekirjoitettava GPG/PGPJa .asc allekirjoituksen sisältävä tiedosto on sisällytettävä jokaiseen tiedostoon.
  • saatavuus pom tiedosto
  • Oikeat arvot groupId, artifactId и version. Versio voi olla mielivaltainen merkkijono, eikä se voi päättyä -SNAPSHOT
  • Läsnäolo vaaditaan name, description и url
  • Lisenssiä, kehittäjiä ja versionhallintajärjestelmää koskevien tietojen läsnäolo

Nämä ovat perussäännöt, joita tulee noudattaa julkaisussa. Täydelliset tiedot saatavilla täällä.

Toteutamme nämä vaatimukset build.gradle tiedosto. Ensin lisätään kaikki tarvittavat tiedot kehittäjistä, lisensseistä, versionhallintajärjestelmästä ja asetetaan myös projektin URL-osoite, nimi ja kuvaus. Kirjoita tähän yksinkertainen menetelmä:

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

Seuraavaksi sinun on määritettävä se luodun kokoonpanon aikana -sources.jar и-javadoc.jar tiedostot. Tätä osiota varten java sinun on lisättävä seuraavat:

java {
    withJavadocJar()
    withSourcesJar()
}

Siirrytään viimeiseen vaatimukseen, GPG/PGP-allekirjoituksen määrittämiseen. Voit tehdä tämän yhdistämällä laajennuksen signing:

plugins {
    id 'signing'
}

Ja lisää osio:

signing {
    sign publishing.publications
}

Lisätään lopuksi osio 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
            }
        }
    }
}

Täällä sonatyyppiKäyttäjänimi и sonatypePassword muuttujat, jotka sisältävät rekisteröinnin yhteydessä luodun käyttäjätunnuksen ja salasanan sonatype.org.

Finaali siis build.gradle näyttää tältä:

Täysi build.gradle-koodi

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

Haluan huomata, että saamme version ympäristömuuttujasta: System.getenv('RELEASE_VERSION'). Paljastamme sen kokoonpanon aikana ja otamme sen tunnisteen nimestä.

PGP-avainten luominen

Yksi Sonatypen vaatimuksista on, että kaikki tiedostot on allekirjoitettava GPG/PGP-avaimella. Tätä varten mennään täällä ja lataa GnuPG-apuohjelma käyttöjärjestelmääsi varten.

  • Luomme avainparin: gpg --gen-key, anna käyttäjänimi, sähköpostiosoite ja aseta myös salasana.
  • Selvitämme id avaimemme komennolla: gpg --list-secret-keys --keyid-format short. Tunnus määritetään kauttaviivan jälkeen, esimerkiksi: rsa2048/9B695056
  • Julkisen avaimen julkaiseminen palvelimelle https://keys.openpgp.org komennolla: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
  • Viemme salaisen avaimen mielivaltaiseen paikkaan, tarvitsemme sitä tulevaisuudessa: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg

Github-toimintojen määrittäminen

Siirrytään viimeiseen vaiheeseen, määritetään koontiversio ja julkaistaan ​​automaattisesti Github Actionsin avulla.
Github Actions on ominaisuus, jonka avulla voit automatisoida työnkulun toteuttamalla täyden CI-/CD-syklin. Rakentamisen, testauksen ja käyttöönoton voivat käynnistää erilaiset tapahtumat: koodin painaminen, julkaisun luominen tai ongelmat. Tämä toiminto on täysin ilmainen julkisille tietovarastoille.

Tässä osiossa näytän sinulle kuinka määrität koonti- ja push-koodin ja otat käyttöön Sonatype-tietovarastoon julkaisun yhteydessä sekä määritän salaisuudet.

Asetamme salaisuuksia

Automaattista kokoonpanoa ja käyttöönottoa varten tarvitsemme useita salaisia ​​arvoja, kuten avaimen tunnus, salasana, jonka annoimme luodessasi avainta, itse PGP-avain ja Sonatype-kirjautumistunnus/salasana. Voit asettaa ne erityisessä osiossa arkiston asetuksissa:

Gradle- ja Github-toimintojen käyttäminen Java-projektin julkaisemiseen Sonatype Maven Central Repositoryssa

Asetamme seuraavat muuttujat:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - kirjautumistunnus / salasana, jonka annoimme rekisteröityessämme Sonatypelle
  • SIGNING_KEYID/SIGNING_PASSWORD — PGP-avaimen tunnus ja salasana asetettu luomisen aikana.

Haluan tarkastella GPG_KEY_CONTENTS-muuttujaa yksityiskohtaisemmin. Tosiasia on, että julkaisemista varten tarvitsemme yksityisen PGP-avaimen. Käytin lähettääkseni sen salaisuuksiin ohjeet ja lisäksi tehnyt useita toimia.

  • Salataan avaimemme gpg:llä: gpg --symmetric --cipher-algo AES256 9B695056.gpgsyöttämällä salasanan. Se tulee sijoittaa muuttujaan: SECRET_PASSPHRASE
  • Käännetään vastaanotettu salattu avain tekstimuodoksi käyttäen base64:ää: base64 9B695056.gpg.gpg > 9B695056.txt. Sisältö sijoitetaan muuttujaan: GPG_KEY_CONTENTS.

Rakenna asetukset, kun painat koodia ja luot PR

Ensin sinun on luotava kansio projektisi juureen: .github/workflows.

Merkitse siihen tiedosto esim. gradle-ci-build.yml seuraavalla sisällöllä:

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

Tämä työnkulku suoritetaan haaroihin työnnettäessä master, dev и testing, myös luotaessa vetopyyntöjä.

Työt-osiossa määritetään määritetyille tapahtumille suoritettavat vaiheet. Tässä tapauksessa rakennamme ubuntun uusimman version, käytämme Java 8:aa ja käytämme myös Gradlen laajennusta eskatos/gradle-command-action@v1joka käyttää rakennusohjelman viimeisintä versiota, joka suorittaa kohdassa määritetyt komennot arguments. Muuttujat secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD nämä ovat salaisuuksia, joita kysyimme aiemmin.

Rakennustulokset näkyvät Toiminnot-välilehdessä:

Gradle- ja Github-toimintojen käyttäminen Java-projektin julkaisemiseen Sonatype Maven Central Repositoryssa

Automaattinen käyttöönotto, kun uusi julkaisu julkaistaan

Luodaan erillinen työnkulkutiedosto automaattista käyttöönottoa varten 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}}

Tiedosto on lähes identtinen edellisen kanssa, lukuun ottamatta tapahtumaa, jossa se laukeaa. Tässä tapauksessa tämä on tapaus, jossa luodaan tunniste, jonka nimi alkaa kirjaimella v.

Ennen käyttöönottoa meidän on purettava PGP-avain salaisuuksista ja asetettava se projektin juureen sekä purettava sen salaus. Seuraavaksi meidän on asetettava erityinen ympäristömuuttuja RELEASE_VERSION johon viittaamme gradle.build tiedosto. Kaikki tämä tehdään osiossa Prepare to publish. Saamme avaimemme muuttujasta GPG_KEY_CONTENTS, käännämme sen gpg-tiedostoksi ja puramme sen salauksen asettamalla sen tiedostoon secret.gpg.

Seuraavaksi siirrymme erityiseen muuttujaan GITHUB_REF, josta saamme version, jonka määritimme tunnistetta luodessasi. Tämä muuttuja on merkityksellinen tässä tapauksessa. refs/tags/v0.0.2 josta leikkasimme pois ensimmäiset 11 merkkiä saadaksemme tietyn version. Seuraavaksi käytämme julkaisussa tavallisia Gradle-komentoja: test publish

Käyttöönoton tulosten tarkistaminen Sonatype-tietovarastossa

Kun julkaisu on luotu, edellisessä osiossa kuvatun työnkulun pitäisi alkaa. Voit tehdä tämän luomalla julkaisun:

Gradle- ja Github-toimintojen käyttäminen Java-projektin julkaisemiseen Sonatype Maven Central Repositoryssa

tagin nimen tulee alkaa v:llä. Jos työnkulku päättyy onnistuneesti Julkaise julkaisu -painikkeen napsautuksen jälkeen, voimme siirtyä osoitteeseen Sonatyyppi Nexus varmistaa:

Gradle- ja Github-toimintojen käyttäminen Java-projektin julkaisemiseen Sonatype Maven Central Repositoryssa

Artefaktti ilmestyi Staging-arkistoon. Se näkyy välittömästi Avaa-tilassa, jonka jälkeen se on siirrettävä manuaalisesti Close-tilaan painamalla asianmukaista painiketta. Kun olet tarkistanut, että kaikki vaatimukset täyttyvät, artefakti siirtyy Close-tilaan eikä sitä voi enää muokata. Tässä muodossa se päätyy MavenCentraliin. Jos kaikki on hyvin, voit painaa nappia Vapauta, ja artefaktti päätyy Sonatype-tietovarastoon.

Jotta artefakti pääsisi MavenCentraliin, sinun on pyydettävä sitä tehtävässä, jonka loimme heti alussa. Sinun tarvitsee tehdä tämä vain kerran, joten julkaisemme ensimmäisen kerran. Myöhemmin tätä ei tarvita, vaan kaikki synkronoidaan automaattisesti. He ottivat synkronoinnin käyttöön nopeasti, mutta kesti noin 5 päivää, ennen kuin artefakti tuli saataville MavenCentralissa.

Siinä kaikki, olemme julkaisseet esineemme MavenCentralissa.

Hyödyllisiä linkkejä

  • Samanlainen artikkeli, julkaise vain mavenin kautta
  • Näyttämöllepano arkisto Sonatyyppi
  • JIRA Sonatype, jossa tehtävä luodaan
  • Esimerkki arkisto, johon kaikki on asennettu

Lähde: will.com