Skip to content

Publish Gradle artifacts to CloudRepo

View as Markdown

Gradle publishes to CloudRepo through its maven-publish plugin: CloudRepo is a Maven repository, so Gradle needs the same repository URL and the same repository token as Maven. This page is for the person who publishes a build. To use what you published, see Gradle and Maven repositories.

  • A Maven repository. If you have none, create one.
  • A repository token that reaches it, with Read + write. A Read only token can pull but not publish: CloudRepo answers gradle publish with 403. See Repository tokens to create one. Your username is the email address of the account that created the token, and your password is the token.
  • Your repository’s URL, https://<organization>.mycloudrepo.io/repositories/<repository>: your organization’s name, then the repository’s name as the admin portal shows it.

1. Keep the credential in ~/.gradle/gradle.properties, outside your project, so it is never committed. The username is your email address, and the password is the token. Keep the file readable by you alone (chmod 600 ~/.gradle/gradle.properties), because it holds the token.

~/.gradle/gradle.properties
cloudrepoUsername=you@example.com
cloudrepoToken=YOUR_REPOSITORY_TOKEN

2. Add a publication and the repository to your build script. The maven-publish plugin must be applied, and your project needs a group and a version. The block reads the credential from the two properties above:

build.gradle.kts
publishing {
publications {
create<MavenPublication>("library") {
from(components["java"])
}
}
repositories {
maven {
url = uri("https://your-org.mycloudrepo.io/repositories/your-repo")
credentials {
username = providers.gradleProperty("cloudrepoUsername").get()
password = providers.gradleProperty("cloudrepoToken").get()
}
}
}
}

A Groovy build script takes the same block:

build.gradle
publishing {
publications {
library(MavenPublication) {
from components.java
}
}
repositories {
maven {
url = "https://your-org.mycloudrepo.io/repositories/your-repo"
credentials {
username = findProperty("cloudrepoUsername")
password = findProperty("cloudrepoToken")
}
}
}
}

3. Publish. Run this in your project’s directory:

Terminal
gradle publish

Expected: BUILD SUCCESSFUL, with a publish...PublicationToMavenRepository task in the output. Gradle uploads the JAR, the POM and a Gradle module metadata file (.module), each with its checksum files, then maven-metadata.xml.

4. Check that it landed. Fetch the POM you published. Put the credential in ~/.netrc and ask curl to read it, and keep the file readable by you alone (chmod 600 ~/.netrc).

~/.netrc
machine your-org.mycloudrepo.io
login you@example.com
password YOUR_REPOSITORY_TOKEN
Terminal
curl --netrc --fail --output docs-gradle-1.0.0.pom \
https://your-org.mycloudrepo.io/repositories/your-repo/com/example/docs/docs-gradle/1.0.0/docs-gradle-1.0.0.pom

The path under the repository URL is your project’s group (dots become slashes), the artifact name (your project’s name), the version and the file. The artifact is also listed in the repository in the admin portal.

Keep the token in your CI’s secret store and hand it to Gradle through the environment, so no file is written. Gradle turns an environment variable named ORG_GRADLE_PROJECT_ plus a property name into that project property, so the same build script works unchanged:

Terminal
export ORG_GRADLE_PROJECT_cloudrepoUsername="you@example.com"
export ORG_GRADLE_PROJECT_cloudrepoToken="$CLOUDREPO_TOKEN"
gradle publish

Give a build in progress a version that ends in -SNAPSHOT, such as version = "1.0.1-SNAPSHOT", and CloudRepo accepts it again on every publish. A release version, one that does not end in -SNAPSHOT, is published once: a second publish to the same version is refused with 409, and the artifact already there stays as it is. See Overwrite Protection, the default setting behind this.

Gradle prints the status it received, such as Could not PUT '...'. Received status code 409 from server: Conflict, and not the explanation CloudRepo sends with it. Check these in order:

  • 401 Unauthorized. The credential was refused. The username must be the email address of the account that created the token, and the password the token itself. A token that is expired or revoked fails the same way: the Repository Tokens page in the admin portal shows its status. In the Kotlin block, a property that Gradle cannot find fails before any request, with Gradle’s own message.
  • 403 Forbidden. The token cannot publish here. A Read only token cannot publish at all, and a token reaches only the repositories ticked when it was created. Use a Read + write token that includes this repository.
  • 409 Conflict. You published a release version that is already in the repository. Nothing is broken: CloudRepo refuses to replace a release on purpose. Publish a new version, or use a -SNAPSHOT version while you iterate. If the repository is meant to accept republished releases, turn Overwrite Protection off in its settings, knowing that a build that resolved that version yesterday can then get different bytes today.
  • 413 Request Entity Too Large. One file is over 50 GB (50,000,000,000 bytes), the most a single file can be.

More: Repository tokens, for every client’s credential; Publish Maven artifacts, if Maven builds your project.