Szerző: Mezei József

Publikáció a Maven Central-ba

Van egy jó ötleted? Vagy már meg is valósítottad? Szeretnéd, hogy más fejlesztők is használhassák? Akkor jó helyen jársz! Megmutatjuk, miként publikálhatod a kódod Maven central-ra és oszthatod meg a megoldásod más fejlesztőkkel is.

Felmerült nálunk az igény arra, hogy a Respresso-hoz kapcsolódóan kódokat tegyünk közzé Maven centralon. Ezért elkezdtünk körülnézni a neten, hogy milyen megoldással juttathatnánk el az állományokat a központi repository-ba. A cikk megírásának pillanatában a következő elfogadott repository szolgáltatók érhetőek el:

A Maven oldalán ezen szolgáltatásokon túl az OSSRH (Open Source Software Respository Hosting) által szolgáltatott repository-t emelik ki mint, a legegyszerűbb publikálási megoldást, melyet a Sonatype üzemeltet. A Maven oldalán található leírás alapján arra a következtetésre jutottunk, hogy számunka is az OSSRH lesz megfelelő, hiszen egyik fent említett szolgáltatásba sem passzolt a projektünk. A következőkben így az OSSRH-n keresztüli publikálásra fogunk fókuszálni.

Az OSSRH követelményei

Elkezdtünk tehát megismerkedni a publikálás folyamatával és követelményeivel. A következő szabályoknak kell jelenleg minden publikáló projektjének megfelelnie:

  • Generáltatni kell Java doc jar-t és sources jar-t
  • Alá kell írnunk a fájlokat GPG/PGP-vel
  • Szerepleniük kell a publikálási információknak (groupId, artifactId, version) a Maven/Gradle fájlban
  • Szükséges a projekt neve és leírása
  • Licencet kell készítenünk a projekthez
  • Meg kell adnunk fejlesztőkről szóló információkat
  • SCM (Source Control Manager) kapcsolatot kell biztosítanunk, amin keresztül a forráskód olvasható

Az SCM információk kivételével mindennek meg tudtunk felelni. Ez azonban egy sarkalatos pont volt, mivel mi nem szerettük volna publikussá tenni a forráskódunkat. Szerencsére nem ijedtünk meg a kihívástól, és átolvastuk a Maven által közzétett, publikálására vonatkozó dokumentációkat.

A kitartó munka eredményesen zárult. Kiderült ugyanis, hogy abban az esetben, ha a forráskód publikálását licenc tiltja, nem kötelező azt közzé tenni, ekkor a pom fájl publikálása is elegendő. Így a kötelezettségnek már mi is meg tudtunk felelni, és nekiláthattunk a teljes folyamat lebonyolításának.

A kód közzétételéről szóló tájékoztatást Te is elolvashatod, kedves érdeklődőnk.  Érdemes a "FAQ and common mistakes" szekciót különös figyelemmel megtekinteni!

Regisztráció és projektindítás

Keressük fel a https://issues.sonatype.org oldalt, ahol rögtön regisztrálnunk is kell magunkat. A bejelentkezést követően azonnal a „Create” felületre kerülünk, ahol egy Issue létrehozását kéri tőlünk a rendszer. Amennyiben mégsem erre a felültre kerültünk, akkor használhatjuk a Create lehetőséget. Ez az Issue fontos lesz még a későbbiekben, ugyanis ezen keresztül tudjuk majd tartani a kapcsolatot az OSSRH ügyintézőivel. Érdemes a lehető legbeszédesebben kitölteni a megjelenő formot, mivel ezt más felhasználók is láthatják, írhatnak hozzá, illetve így nekünk is kevesebb akadályon kell átküzdenünk magunkat a későbbiekben.

 

Minta a kitöltéshez:

Project: Community Support - Open Source Project Repository Hosting (OSSRH)

Issue Type: New Project

Summary: Megosztani kívánt projekt egysoros összefoglalója.

Descirption: Megosztani kívánt projekt részletesebb leírása. Érdemes több sorban megfogalmaznunk, hogy miket publikálunk a későbbiekben a groupId alatt.

GroupId: azonosító, ami a fejlesztőt azonosítja (pl.: ponte.hu)

Project url: ezen a linken található a projekt leírása

SCM url: azon verziókezelő, ahol a projekt  vagy pom fájl található

 

Kitöltöttünk minden mezőt, majd vártuk az OSSRH jelentkezését. Szerencsére nem kellett túl sokat, mivel 24 órán belül meg is kaptuk a számunkra szükséges tájékoztatást. Kérésük alapján igazolnunk kellett, hogy a ponte.hu domain a birtokunkban van. Ennek bizonyításához be kellett állítanunk egy általuk megadott DNS rekordot, valamint írnunk kellett számukra egy emailt a pontés címünkről. Ezek után pár napon belül átestünk az ellenőrzésen és már publikálhattuk is a kódunkat.

Első deploy

Sikeresen regisztráltunk és már égtünk a vágytól, hogy kirakhassuk a kódunkat. Mivel az OSSRH rendelkezik SNAPSHOT repository-val, és a SNAPSHOT verzió publikálásához elegendő csupán a regisztráció, a feljebb említett követelmények teljesítése nélkül, így ennek nem láttuk akadályát. A kód SNAPSHOT változatának pubikálása természetesen nem kötelező eleme a folyamatnak, azonban a kód éles környezetben való kipróbálásához megfelelő környzetet biztosít.

A SNAPSHOT verzió használatával felül tudjuk írni a korábbi publikációnkat a verziószám megtartásával. A függőségkezelők pedig (majdnem) minden build előtt ellenőrzik, hogy van-e friss változat az adott függőségből. A „majdnem” csupán az időfaktor miatt szerepel a mondatban, hiszen felesleges percenként ellenőrizni a repository tartalmát.

Amennyiben Maven függőség kezelőt használunk, konfiguráljuk a következő módon:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>hu.ponte.sample</groupId>
   <artifactId>sample-artifact</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>Sample deploy project</name>
   <description>This is a sample project to introduce a publish process.</description>
   <url>https://github.com/pontehu</url>
   <inceptionYear>2019</inceptionYear>


   <distributionManagement>
      <snapshotRepository>
         <id>ossrh</id>
         <url>https://oss.sonatype.org/content/repositories/snapshots</url>
      </snapshotRepository>
   </distributionManagement>
   <build>
      <plugins>
         <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <version>current_version</version>
            <extensions>true</extensions>
            <configuration>
               <serverId>ossrh</serverId>
               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
               <autoReleaseAfterClose>true</autoReleaseAfterClose>
            </configuration>
         </plugin>
      </plugins>
   </build>
</project>

Ezek után állítsuk be a publikáláshoz szükséges privilégiumokat. Ezt a settings.xml-ben tudjuk megtenni, melyet a USER_HOME/.m2/settings.xml útvonalon érhetünk el:

<settings>
  <servers>
    <server>
      <id>ossrh</id>
      <username>your-jira-id</username>
      <password>your-jira-password</password>
    </server>
  </servers>
</settings>

Gradle típusú függéségkezelő használata esetén éljünk egy apró trükkel a publikálási folyamat megírása előtt. Szervezzük külön gradle fájlba a publikálást, ezt mi mavencetral.gradle-nek fogjuk elnevezni. A fájlt helyezzük azonos könyvtárba a build.gradle-lel, amelyen keresztül importálni fogjuk. Az említett build.gradle fájlba, a projekt modul típust követően helyezzük el a következő sort:

apply from: 'mavencentral.gradle'

A későbbikben már csak a frissen létrehozott mavencentral.gradle fájlba fogunk dolgozni. Egészítsük is ki a következő sorokkal:

apply plugin: 'maven'
def getSnapshotRepositoryUrl() {
    return "https://oss.sonatype.org/content/repositories/snapshots/"
}
afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                pom.groupId = 'hu.ponte.sample'
                pom.artifactId = 'sample-artifact'
                pom.version = '0.0.1-SNAPSHOT'
                snapshotRepository(url: getSnapshotRepositoryUrl()) {
                    authentication(userName: ossrhUsername, password: ossrhPassword)
                }

                pom.project {
                    name = 'Sample deploy project'
                    packaging = 'jar/aar'
                    description = 'This is a sample project to introduce a publish process'
                    url = 'https://github.com/pontehu' 
scm { url = 'https://github.com/pontehu' connection = 'scm:git:git://github.com/pontehu/sample.git' developerConnection = 'scm:git:git://github.com/pontehu/sample.git' } } } } } } dependencies { }

Állítsuk be a publikáláshoz szükséges privilégiumokat, melyet a properties.gradle fájlban tudunk megtenni:

ossrhUsername=sampleUser
ossrhPassword=samplePass

A gradle.properties fájl több helyről is elérhető lehet a program számára:

  • a projektünk főkönyvtárában (ahol a build script található)
  • alprojekt mappájában
  • a gradle user home-ban (USER_HOME/.gradle)

Majd válasszuk az uploadArchives lehetőséget. A Deploy sikerességét azonnal le is tudjuk ellenőrizni, ugyanis a https://oss.sonatype.org/content/repositories/snapshots/ oldalon megtalálható minden sikeresen publikált projekt. Ezeket a publikációkat ettől fogva már akár függőségként is használhatjuk.

Maven
Gradle
<repositories>
	<repository>
		<id>oss</id>
		<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
	</repository>
</repositories>
buildscript {
    repositories {
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
}

allprojects {
    repositories {
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
}

 

Jöjjön az éles verzió

Az éles kiadáshoz pár dolgot még be kell állítanunk. A feljebb bemutatott követelményeknek eddig nem feleltünk meg maradéktalanul, így pótolni fogjuk a hiányzókat, hiszen az összes elvárásnak való megfelelés elengedhetetlen az éles verzió publikálásához.

Javadoc

A feltölteni kívánt állományhoz generáltatnuk kell egy uploaded-project-name-javadoc.jar állományt. Amennyiben a publikálni kívánt kód java nyelven íródott, a Maven javadoc függősége elegendő lehet számunkra:

 <build>
   <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
         <version>current_version</version> 
         <executions> 
            <execution> 
               <id>attach-javadocs</id> 
                  <goals> 
                     <goal>jar</goal> 
                  </goals> 
            </execution> 
        </executions> 
     </plugin>
  </plugins>
</build> 

Mi azonban Kotlin kódot írtunk, és abból szerettünk volna javadoc-ot generáltatni. Ennek megfelelően a package hierarchiánk is kotlin/hu/ponte/sample/… -ként alakult. Ez esetben a javadoc függőség már nem volt megfelelő. Keresnünk kellett tehát egy olyan megoldást, ami Kotlin fájlokból is képes javadoc-ot generálni. Ekkor találtunk rá a dokka-ra.

Maven
Java
Android
<build>
	<plugins>
		<plugin>
			<groupId>org.jetbrains.dokka</groupId>
			<artifactId>dokka-maven-plugin</artifactId>
			<version>current_version</version>
			<executions>
				<execution>
					<phase>package</phase>
					<goals>
						<goal>javadocJar</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<sourceDirectories>
					<dir>src/main/kotlin</dir>
					</sourceDirectories>
			</configuration>
		</plugin>
	</plugins>
</build>
buildscript {
	repositories {
		jcenter()
	}

	dependencies {
		classpath "org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}"
	}
}

apply plugin: 'org.jetbrains.dokka'

dokka {
	outputFormat = 'javadocJar'    
	// These tasks will be used to determine source directories and classpath 
	sourceDirs = files('src/main/kotlin')	
}	
buildscript {
	repositories {
		google()
		jcenter()
	}
					
	dependencies {
		classpath 'com.android.tools.build:gradle:3.3.1'
		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
		classpath "org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}"
		classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}"
		// NOTE: Do not place your application dependencies here; they belong
		// in the individual module build.gradle files
	}
}

apply plugin: 'org.jetbrains.dokka-android'

dokka {
	moduleName = 'data'
	outputFormat = 'javadoc'
	outputDirectory = "$buildDir/javadoc"
	sourceDirs = files('src/main/java')
}

task androidJavadocsJar(type: Jar) {
	classifier = 'javadoc'
	from android.sourceSets.main.java.srcDirs
}
artifacts {
	archives androidJavadocsJar
}			

Amennyiben groovy kódból szeretnénk docot generáltatni:

buildscript {
	repositories {
		google()
		jcenter()

	}
	
	dependencies {
		classpath 'com.android.tools.build:gradle:$gradle_version'
		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
		classpath "org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}"
		classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}"
		// NOTE: Do not place your application dependencies here; they belong
		// in the individual module build.gradle files
		}
}

apply plugin: 'org.jetbrains.dokka'

dokka {
	moduleName = 'data'
	outputFormat = 'javadoc'
	outputDirectory = "$buildDir/javadoc"

	sourceDirs = files('src/main/groovy')
}

task androidJavadocsJar(type: Jar) {
	classifier = 'javadoc'
	from sourceSets.main.runtimeClasspath
}

artifacts {
	archives androidJavadocsJar
}	

A javadoc-ot követően szükséges egy forrásokat tartalmazó jar generálása is. Ez esetében a hagyományos, Maven által szolgáltatott generátor is jól használható:

Maven
Java
Android
<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-source-plugin</artifactId>
			<version>current_version</version> 
			<executions> 
				<execution> 
					<id>attach-sources</id> 
					<goals> 
						<goal>jar-no-fork</goal> 
					</goals> 
				</execution> 
			</executions> 
		</plugin> 
	</plugins>
</build> 
task sourcesJar(type: Jar) {
	classifier = 'sources'
	from sourceSets.main.allSource
}

artifacts {
	archives sourcesJar    
}
task sourcesJar(type: Jar) {
	classifier = 'sources'
	from android.sourceSets.main.java.sourceFiles
}

artifacts {
	archives androidJavadocsJar
	archives sourcesJar
}

 

Állományok titkosítása GPG/PGP használatával

A forráskódunkat titkosítanunk kell mielőtt közzé tesszük, tehát szükségünk van egy GPG kliensre. A https://www.gnupg.org/download/ oldalon megtalálhatjuk az operációs rendszerünknek megfelelő GPG változatot.

  • Windows esetén használhatjuk a Kleopatra klienst
  • Linux esetén a GnuPG klienst
  • Mac-en a GPGSuit klienst

A kulcsok generálásának és megosztásának folyamatáról részletes információ érhető el az alábbi oldalon: https://central.sonatype.org/pages/working-with-pgp-signatures.html. A sikeres kulcs generálást követően használjuk a publikáláshoz készített függőségeket.

Windows esetén a frissen telepített GPG kliens miatt indítsuk újra az Android Studio-t vagy IntelliJ-t.

Maven
Java
Android
<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-gpg-plugin</artifactId>
			<version>current_version</version> 
			<executions> 
				<execution> 
					<id>ossrh</id> 
					<phase>verify</phase> 
					<goals> 
						<goal>sign</goal> 
					</goals> 
				</execution> 
			</executions> 
		</plugin> 
	</plugins> 
</build> 
apply plugin: 'signing'

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
        useGpgCmd()
        sign configurations.archives
    }

beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
apply plugin: 'signing'

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
        useGpgCmd()
        sign configurations.archives
    }

A gradle properties fájlba szúrjuk be a következő sorokat: signing.gnupg.executable=gpg signing.gnupg.useLegacyGpg=true signing.gnupg.homeDir=../../../../Users/USER_NAME/AppData/Roaming/gnupg

Az útvonal megadása szükséges, mivel a Gradle alatt futó GPG kliensnek szüksége van a pubringre és hozzá tartozó fájlokra a helyes működéshez. (Kulcs importálást követően a kliens ugyanúgy legyártja ezeket a fájlokat.) A fentebb említett szignatúra Windows rendszer esetén értendő, Linuxon és Mac-en a felhasználói név alatti megfelelő mappában keresendők a gpg-hez tartozó fájlok.

A release szerverre való publikációhoz szükséges továbbá felhasználói tokent és jelszót is generáltatnunk. Ehhez a művelethez keressük fel a https://oss.sonatype.org/ oldalt és jelentkezzünk be. A jobb felső sarokban található felhasználónévre kattintva válasszuk a Profile lehetőséget. Az itt megjelenő legördülő menüben kattintsunk a User Token lehetőségre, majd az Access User Token gombra. A megjelenő adatokat tudjuk a későbbikben publikálásra használni. Az első mezőben a felhasználónév, a másodikban a jelszó kapott helyet. Kezeljük ezeknek tartalmát bizalmasan! Helyezzük el a gradle properties-be, illetve a settings.xml-be a tartalmat.

Maven
Gradle
<settings>
  <servers>
    <server>
      <id>ossrh</id>
      <username>mavenUsername</username>
      <password>mavenPassword</password>
    </server>
  </servers>
</settings>
mavenUsername=aaa
mavenPassword=bbb
signin.keyId=2134

 

Licenc és fejlesztői információk megadása

Érdemes alaposan körülnézni a megfelelő licenc kiválasztásához, hiszen ez határozza meg a kódunk felhasználhatóságát. A licencen természetesen utólag is lehet módosítani mind engedni, mind megszorítani rajta.

Maven
Gradle
<organization>
	<name>Ponte.hu Kft.</name>
	<url>https://ponte.hu</url>
</organization>

<licenses>
	<license>
		<name>Sync client MIT License</name>
		<url>https://github.com/pontehu/.../LICENSE.txt</url>
	</license>
</licenses>

<developers>
	<developer>
		<name>Ponte</name>
		<email>info@respresso.io</email>
		<organization>ponte.hu Kft.</organization>
		<organizationUrl>https://ponte.hu</organizationUrl>
	</developer>
</developers>

<scm>
	<connection>scm:git:git://github.com/pontehu/sample.git</connection>
	<developerConnection>scm:git:ssh://github.com:pontehu/sample.git</developerConnection>
	<url>https://github.com/pontehu/respresso-sync-for-clients</url>
</scm>
url = 'https://github.com/pontehu/respresso-client-android'
scm {
	url = 'https://github.com/pontehu/sample'
 	connection = 'scm:git:git://github.com/pontehu/sample.git'
	developerConnection = 'scm:git:ssh://github.com:pontehu/sample.git'
}

licenses { 	
	license { 		
		name = 'Sync client MIT License' 		
		url = 'https://github.com/pontehu/.../LICENSE.txt' 	
	}
} 

developers { 	
	developer { 		
		id = 'pontehu' 		
		name = 'Ponte' 		
		email = 'info@respresso.io' 		
		organization = 'ponte.hu Kft.' 		
		organizationUrl = 'https://ponte.hu' 	
	}
} 

 

OSS utolsó simítások

A sikeres deploy-t követően fel kell keresnünk a https://oss.sonatype.org oldalt. Jelentkezzünk be, majd válasszuk a Staging repository lehetőséget az oldalsó menüben. A listázott elemek között megtalálhatjuk az általunk feltöltött artifactot. Jelöljük ki, és nézzük meg az Activity fül alatt, hogy minden akció sikeresen lefutott e. Ekkor választhatunk a következő lehetőségek közül:

  1. Drop lehetőség a kódunk törléséhez. Az opció lehetőséget ad nekünk a problémák javítására és a deploy folyamat újbóli futtatására.
  2. Kattinthatunk a Close lehetőségre is, amennyiben folytatni szeretnénk a publikálást. A Close-t követően válasszuk a Release lehetőséget a kód Maven central-ba való küldéséhez. A publikálás akár 1-3 órán át is tarthat. Miután a publikálás sikeresen megtörtént, ellenőrizzük le, hogy minden rendben zajlott-e. A sikeres release-t követően érdemes plusz egy kommentben megjegyezni az OSSRH felé, hogy sikeresen kiment az első verzió, így ők aktiválhatják a későbbi szinkronizációs folyamatot. Aktíválást követően az újabb éles verziók publikálása automatikusan megtörténik és körülbelül 15 percen belül használható is a frissen publikált kód. A friss verzó Maven central front-end-en való megjelenítése azonban több óráig is eltarthat. 

 

Végleges változatok

A licencre és a fejlesztőkre vonatkozó információkat még nem adtuk meg a függőségkezelőnkben, ezért ezeket most pótoljuk. Nézzük meg a fájlok végleges tartalmát:

Maven
Java
Android
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

	<groupId>hu.ponte.sample</groupId>
	<artifactId>sample-artifact</artifactId>
	<version>0.0.1</version>
	<packaging>jar</packaging>
	<modelVersion>4.0.0</modelVersion>
	<name>Sample deploy project</name>
	<description>This is a sample project to introduce a publish process</description>
	<url>https://github.com/pontehu</url>
	<inceptionYear>2019</inceptionYear>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<organization>
		<name>Ponte.hu Kft.</name>
		<url>https://ponte.hu</url>
	</organization>

	<licenses>
		<license>
			<name>Sync client MIT License</name>
			<url>https://github.com/pontehu/.../LICENSE.txt</url>
		</license>
	</licenses>

	<developers>
		<developer>
			<name>Ponte</name>
			<email>info@ponte.hu</email>
			<organization>ponte.hu Kft.</organization>
			<organizationUrl>https://ponte.hu</organizationUrl>
		</developer>
	</developers>

	<scm>
		<connection>scm:git:git://github.com/pontehu/sample.git</connection>
		<developerConnection>scm:git:ssh://github.com:pontehu/sample.git</developerConnection>
		<url>https://github.com/pontehu/sample</url>
	</scm>

	<dependencies>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>current_version</version>
				<configuration>
					<source>8</source>
					<target>8</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<version>current_version</version>
				<executions>
					<execution>
						<id>attach-sources</id>
						<goals>
							<goal>jar</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.sonatype.plugins</groupId>
				<artifactId>nexus-staging-maven-plugin</artifactId>
				<version>current_version</version>
				<extensions>true</extensions>
				<configuration>
					<serverId>ossrh</serverId>
					<nexusUrl>https://oss.sonatype.org/</nexusUrl>
					<autoReleaseAfterClose>true</autoReleaseAfterClose>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-gpg-plugin</artifactId>
				<version>current_version</version>
				<executions>
					<execution>
						<id>ossrh</id>
						<phase>verify</phase>
						<goals>
							<goal>sign</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.jetbrains.dokka</groupId>
				<artifactId>dokka-maven-plugin</artifactId>
				<version>current_version</version>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>javadocJar</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<sourceDirectories>
						<dir>src/main/kotlin</dir>
					</sourceDirectories>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<distributionManagement>
		<snapshotRepository>
			<id>ossrh</id>
			<url>https://oss.sonatype.org/content/repositories/snapshots</url>
		</snapshotRepository>
		<repository>
			<id>ossrh-staging</id>
			<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
		</repository>
	</distributionManagement>
</project>
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: 'org.jetbrains.dokka

sourceSets {
    main {
        java {
            srcDir 'src/groovy'
        }
        resources {
            srcDir 'src/resources'
        }
    }
}

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
    return "https://oss.sonatype.org/content/repositories/snapshots/"
}

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

                pom.groupId = 'hu.ponte.sample'
                pom.artifactId = 'sample-artifact'
                pom.version = '0.0.1'

                repository(url: getReleaseRepositoryUrl()) {
                    authentication(userName: mavenUsername, password: mavenPassword)
                }
                snapshotRepository(url: getSnapshotRepositoryUrl()) {
                    authentication(userName: ossrhUsername, password: ossrhPassword)
                }

                pom.project {
                    name = 'Sample deploy project'
                    packaging = 'jar'
                    description = 'This is a sample project to introduce a publish process'
                    url = 'https://github.com/pontehu/sample'

                    scm {
                        url = 'https://github.com/pontehu/sample'
                        connection = 'scm:git:git://github.com/pontehu/sample.git'
                        developerConnection = 'scm:git:git://github.com/pontehu/sample.git'
                    }

                    licenses {
                        license {
                            name = 'Sync client MIT License'
                            url = 'https://github.com/pontehu/.../LICENSE.txt'
                        }
                    }

                    developers {
                        developer {
                            id = 'pontehu'
                            name = 'Ponte'
                            email = 'info@ponte.hu'
                            organization = 'ponte.hu Kft.'
                            organizationUrl = 'https://ponte.hu'
                        }
                    }
                }
            }
        }
    }

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
//        useGpgCmd()
        sign configurations.archives
    }

    task androidJavadocs(type: Javadoc) {
        source = sourceSets.main.java.srcDirs
        classpath += sourceSets.main.runtimeClasspath
    }

    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        classifier = 'javadoc'
        from sourceSets.main.allSource
    }

    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from sourceSets.main.allSource
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocsJar
    }
}
dependencies {}
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: 'org.jetbrains.dokka-android'

dokka {
    moduleName = 'data'
    outputFormat = 'javadoc'
    outputDirectory = "$buildDir/javadoc"

    sourceDirs = files('src/main/java')
}

task androidJavadocsJar(type: Jar) {
    classifier = 'javadoc'
    from android.sourceSets.main.java.srcDirs
}

task sourcesJar(type: Jar) {
    classifier = 'sources'
    from android.sourceSets.main.java.sourceFiles
}

def isReleaseBuild() {
    return version.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
    return "https://oss.sonatype.org/content/repositories/snapshots/"
}

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

                pom.groupId = 'hu.ponte.sample'
                pom.artifactId = 'sample-artifact'
                pom.version = '0.0.1'
				repository(url: getReleaseRepositoryUrl()) {
                    authentication(userName: mavenUsername, password: mavenPassword)
                }

                snapshotRepository(url: getSnapshotRepositoryUrl()) {
                    authentication(userName: ossrhUsername, password: ossrhPassword)
                }

                pom.project {
                    name = 'Sample deploy project'
                    packaging = 'aar'
                    description = 'This is a sample project to introduce a publish process'
                    url = 'https://github.com/pontehu/sample'

                    scm {
                        url = 'https://github.com/pontehu/sample'
                        connection = 'scm:git:git://github.com/pontehu/sample.git'
                        developerConnection = 'scm:git:git://github.com/pontehu/sample.git'
                    }
                }
            }
        }
    }

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
//        useGpgCmd()
        sign configurations.archives
    }

    artifacts {
        archives androidJavadocsJar
        archives sourcesJar
    }
}
dependencies {}
Ha tetszett a cikk oszd meg másokkal is.