Code Monkey home page Code Monkey logo

publish-package's Introduction

This project demonstrates how to publish a Gradle project to OSSRH. Refer to build.gradle for a complete working sample.

build.gradle

The following steps discuss how to configure the build.gradle for deploying to OSSRH.

Apply Plugins

The first step is to apply the necessary plugins:

build.gradle
plugins {
	id "java"
	id "signing"
	id "maven-publish"
	id "io.github.gradle-nexus.publish-plugin" version "1.0.0"
}
  • We apply the Java Plugin to use Gradle’s standard Java conventions. This is applied to every project that is deployed.

  • We apply the Signing Plugin to sign the Maven artifacts. This is applied to every project that is deployed.

  • We apply the maven-publish adds the ability to publish our artifacts. This is applied to every project that is deployed.

  • We apply the io.github.gradle-nexus.publish-plugin to manage the staging repository in OSSRH. This is applied only to the root project.

Configure group

We configure the group so it can be used to default the group in the pom:

build.gradle
group = "io.rwinch.sample"

Configure Gradle Publications

Here we configure the Gradle Publications (i.e. what will be published to the repository). In our example, we configure a publication named maven that contains all of the java compoonents. This is applied to every project that is deployed.

build.gradle
publishing {
	publications {
		maven(MavenPublication) {
			from(components.java)
		}
	}
}

OSSRH Requirements

Next we must ensure that all of the OSSRH requirements are met. This is applied to every project that is deployed.

The following code generates the required Javadoc and Sources using Gradle’s Java extension.

build.gradle
java {
	withJavadocJar()
	withSourcesJar()
}

The following code configures the Signing Plugin to generate the required signatures if the Gradle property signingKey or signingKeyId is found.

build.gradle
def hasSigningKey = project.hasProperty("signingKeyId") || project.hasProperty("signingKey")
if(hasSigningKey) {
	sign(project)
}
void sign(Project project) {
	project.signing {
		required { project.gradle.taskGraph.hasTask("required") }
		def signingKeyId = project.findProperty("signingKeyId")
		def signingKey = project.findProperty("signingKey")
		def signingPassword = project.findProperty("signingPassword")
		if (signingKeyId) {
			useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
		} else if (signingKey) {
			useInMemoryPgpKeys(signingKey, signingPassword)
		}
		sign publishing.publications.maven
	}
}

Next we need to ensure that Gradle is configured to customize the pom in order to ensure the required metadata is present in the Maven pom. The groupId, artifactId, and vession of the pom are defaulted by the maven-publish plugin.

build.gradle
project.plugins.withType(MavenPublishPlugin).all {
	PublishingExtension publishing = project.extensions.getByType(PublishingExtension)
	publishing.publications.withType(MavenPublication).all { mavenPublication ->
		mavenPublication.pom {
			name = "${project.group}:${project.name}"
			description = name
			url = "https://github.com/rwinch/gradle-publish-ossrh-sample"
			licenses {
				license {
					name = "The Apache License, Version 2.0"
					url = "https://www.apache.org/licenses/LICENSE-2.0"
				}
			}
			developers {
				developer {
					id = "rwinch"
					name = "Rob Winch"
					email = "[email protected]"
				}
			}
			scm {
				connection = "scm:git:https://github.com/rwinch/gradle-publish-ossrh-sample"
				developerConnection = "scm:git:ssh://github.com/rwinch/gradle-publish-ossrh-sample.git"
				url = "https://github.com/rwinch/gradle-publish-ossrh-sample"
			}
		}
	}
}

Configure Gradle Nexus Publishing Plugin

We configure the Gradle Nexus Publishing Plugin. By default it uses credentials configured as the project properties sonatypeUsername and sonatypePassword. This is only configured on the root project.

If you registered with Sonatype after 24 February 2021 to publish to Maven Central, then you must set your nexusUrl and snapshotRepositoryUrl manually. See https://central.sonatype.org/news/20210223_new-users-on-s01/ for more information.

build.gradle
nexusPublishing {
	repositories {
		sonatype()    //sonatypeUsername and sonatypePassword properties are used automatically

		// OR, if you registered with Sonatype after 24 February 2021
		// sonatype {
		//	    nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
		//	    snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
		// }
	}
	// these are not strictly required. The default timeouts are set to 1 minute. But Sonatype can be really slow.
	// If you get the error "java.net.SocketTimeoutException: timeout", these lines will help.
	connectTimeout = Duration.ofMinutes(3)
	clientTimeout = Duration.ofMinutes(3)
}

Publishing Local

Finally, we set up a repository on our local file system in the build directory, so that we can easily test publishing independant of OSSRH. This is not required, but it makes troubleshooting easier. This is applied to every project that is deployed.

build.gradle
publishing {
	repositories {
		maven {
			name = "local"
			// change URLs to point to your repos, e.g. http://my.org/repo
			def releasesRepoUrl = "$buildDir/repos/releases"
			def snapshotsRepoUrl = "$buildDir/repos/snapshots"
			url = version.endsWith("SNAPSHOT") ? snapshotsRepoUrl : releasesRepoUrl
		}
	}
}

Gradle Tasks

The configuration we use requires the following Gradle Properties to be set:

  • signingKey the pgp used to sign the artifacts. Generate gpg key with command gpg --export-secret-keys --armor F207B5A1 > my.gpg. F207B5A1 is last 8 characters in the public key, you can get public key by gpg --list-keys

  • signingPassword the password for the signingKey and my.gpg.pgp.

  • sonatypeUsername the username from sonatype used to publish artifacts. This is the token username, not the one used for logging into the UI.

  • sonatypePassword the password from sonatype used to publish artifacts. This is the token password, not the one used for logging into the UI.

The following will provide all the Gradle Properties necessary for the commands below using environment variables.

export ORG_GRADLE_PROJECT_signingKey=`cat my.gpg`
export ORG_GRADLE_PROJECT_signingPassword=password
export ORG_GRADLE_PROJECT_sonatypeUsername=<replace-with-your-token-username>
export ORG_GRADLE_PROJECT_sonatypePassword=<replace-with-your-token-password>

When you first set up the code or need to troubleshoot signing process, you can run the signMavenPublication task.

$ ./gradlew signMavenPublication
$ tree build/libs
build/libs
├── publish-ossrh-sample-1.0.0.jar
├── publish-ossrh-sample-1.0.0.jar.asc
├── publish-ossrh-sample-1.0.0-javadoc.jar
├── publish-ossrh-sample-1.0.0-javadoc.jar.asc
├── publish-ossrh-sample-1.0.0-sources.jar
└── publish-ossrh-sample-1.0.0-sources.jar.asc

You can also test what is going to be published using the local publication to publish to a directory on your local machine. You will notice, if we have defined the signing properties, that all of our artifacts (jars, javadoc, pom, etc) are also signed.

$ ./gradlew publishMavenPublicationToLocalRepository
$ tree build/repos/releases/
build/repos/releases/
└── io
    └── rwinch
        └── sample
            └── publish-ossrh-sample
                ├── 1.0.0
                │    ├── publish-ossrh-sample-1.0.0.jar
                │    ├── publish-ossrh-sample-1.0.0.jar.asc
                │    ├── publish-ossrh-sample-1.0.0.jar.asc.md5
                │    ├── publish-ossrh-sample-1.0.0.jar.asc.sha1
                │    ├── publish-ossrh-sample-1.0.0.jar.asc.sha256
                │    ├── publish-ossrh-sample-1.0.0.jar.asc.sha512
                │    ├── publish-ossrh-sample-1.0.0.jar.md5
                │    ├── publish-ossrh-sample-1.0.0.jar.sha1
                │    ├── publish-ossrh-sample-1.0.0.jar.sha256
                │    ├── publish-ossrh-sample-1.0.0.jar.sha512
                │    ├── publish-ossrh-sample-1.0.0-javadoc.jar
                │    ├── publish-ossrh-sample-1.0.0-javadoc.jar.asc
...

If you publish to OSSRH it will automatically create a staging repository if the version looks like a release:

$ ./gradlew publishToSonatype

Now visit https://oss.sonatype.org/#stagingRepositories and you can view the staged repository using the Sonatype username and password (the UI one not the token).

We can publish and close the repository all at once:

$ ./gradlew publishToSonatype closeSonatypeStagingRepository

If you want to release the staged repository as well, then you can perform:

$ ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
Note
If you want to perform some additional checks before you release the repository, you can create a task that mustRunAfter the closeSonatypeStagingRepository task and ensure that the releaseSonatypeStagingRepository task depends on it. The staging repository can be accessed at https://oss.sonatype.org/service/local/repositories/{staging-id}/content

Publish by action

To make publish automatic by action in github.

Fist to add repository secrets:

  • SIGNING_KEY the pgp used to sign the artifacts. Generate gpg key with command gpg --export-secret-keys --armor F207B5A1 > my.gpg. use cat my.gpg to output secret key in the console and copy the output as the vale of SIGNING_KEY. F207B5A1 is last 8 characters in the public key, you can get public key by gpg --list-keys

  • SIGNING_PASSWORD the password for the SIGNING_KEY.

  • OSSRH_TOKEN_USERNAME the username from sonatype used to publish artifacts. This is the token username, not the one used for logging into the UI.

  • OSSRH_TOKEN_PASSWORD the password from sonatype used to publish artifacts. This is the token password, not the one used for logging into the UI.

Second to create publish script in the github action, please add the publish.yml file in the .github/workflows

name: Publish

env:
  ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.OSSRH_TOKEN_USERNAME }}
  ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.OSSRH_TOKEN_PASSWORD }}
  ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
  ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}

on:
  push:
    tags:
      - 'v[0-9]+\.[0-9]+'

jobs:
  publish:
    name: Release build and publish
    runs-on: ubuntu-22.04
    steps:
      - name: Check out code
        uses: actions/[email protected]
      - name: Set up JDK 17
        uses: actions/[email protected]
        with:
          distribution: adopt
          java-version: 17
      - name: Build
        run: ./gradlew signMavenPublication publishMavenPublicationToLocalRepository
      - name: Publish to NEXUS
        run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

Third to change and update the version variable in the build.gradle file. If you do not update version, there will be failed for releaseSonatypeStagingRepository, because version confilicate with the package have been released.

So if you create a new tag like v1.0, the workflow will run and the package will publish to the remote repository.

publish-package's People

Contributors

thebestornothing avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.