Skip to content

Instantly share code, notes, and snippets.

@vlsi
Last active April 28, 2020 18:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlsi/8daf6cc64c91d1d59e899caa13dd18dc to your computer and use it in GitHub Desktop.
Save vlsi/8daf6cc64c91d1d59e899caa13dd18dc to your computer and use it in GitHub Desktop.
Publishing Gradle-based Java artifacts to a custom Nexus repository

Apache Maven enables developers to augment repository URL via settings.xml. That might sound powerful, however, it requires to use the same repository IDs across all the projects which might not be always possible.

Let's see how Gradle-based project can be published to a custom repository.

For instance, let's try to publish Apache Calcite to our own Nexus instance. Of course we don't want to commit the URL and password of our secretNexus to GitHub, so we need to augment the build without touching the files.

Gradle has Initialization Scripts that enable users to augment all the builds without touching project-specific files.

All we need is to add the publishing repository via init.gradle.kts:

// You could place this as $HOME/.gradle/init.gradle.kts
// See more ways to apply init scripts here: https://docs.gradle.org/current/userguide/init_scripts.html#sec:using_an_init_script

// This adds "secretNexus" publishing repository to all the projects
allprojects {
    plugins.withId("maven-publish") {
        configure<PublishingExtension> {
            repositories {
                maven {
                    name = "secretNexus"
                    val baseUrl = "https://localhost/qwerty"
                    val releasesUrl = "$baseUrl/repository/maven-releases"
                    val snapshotsUrl = "$baseUrl/repository/maven-snapshots"
                    val release = !project.version.toString().endsWith("-SNAPSHOT")
                    url = uri(if (release) releasesUrl else snapshotsUrl)
                    credentials {
                        username = "xxx"
                        password = "xxx"
                    }
                }
            }
        }
     }
}

That is it. Now Gradle will be able to publish the artifacts to the newly created repository:

$ gw tasks

Publishing tasks
----------------
publish - Publishes all publications produced by this project.
publishAllPublicationsToSecretNexusRepository - Publishes all Maven publications produced by this project to the secretNexus repository.
publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.

Oh, great. Now we have publishAllPublicationsToSecretNexusRepository task for publishing the artifacts to our repository. We are all set, so we could execute it:

$ gw publishAllPublicationsToSecretNexusRepository

Securing the repository

Adding the repository by default might be convenient, however, you might want to avoid adding it for every build you run. Luckily, init.gradle.kts is a regular Kotlin code, so you could add if there.

Let's configure it to add the repository only in case -DaddSecretNexusRepository is present on the command line:

if (gradle.startParameter.systemPropertiesArgs.get("addSecretNexusRepository")?.toBoolean() == true) {
    allprojects {
        ...
    }
}

This configuration might make your builds 99.42% more secure as the repository (and its credentials!) won't be visible to the untrusted build scripts by default.

PS. gw comes from gdub. I would recommend giving it a try.

@julianhyde
Copy link

A wrapper around a wrapper!? Reminds me of rvm and rbenv. This can only end badly.

gradle should do what gw does - look for a gradlew and, if it exists and is a different version, use it.

@julianhyde
Copy link

Thanks for this fragment. In order to make it work for releases, I needed to add code to switch between snapshot and release URLs:

                    val baseUrl = "https://localhost/qwerty"
                    val releasesUrl = "$baseUrl/repository/maven-releases"
                    val snapshotsUrl = "$baseUrl/repository/maven-snapshots"
                    val release = !project.version.toString().endsWith("-SNAPSHOT")
                    url = uri(if (release) releasesUrl else snapshotsUrl)

@vlsi
Copy link
Author

vlsi commented Apr 28, 2020

gradle should do what gw does

Technically speaking, it is known as gradle/gradle#1368, however someone needs to spend time on implementing that :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment