Single Module Project Example¶
This guide shows how to set up the Central Portal Publisher plugin for a single-module Java or Kotlin project.
Project Structure¶
my-library/
├── build.gradle.kts
├── gradle.properties
├── settings.gradle.kts
└── src/
├── main/
│ └── kotlin/
│ └── com/example/MyLibrary.kt
└── test/
└── kotlin/
└── com/example/MyLibraryTest.kt
Complete Example¶
build.gradle.kts¶
plugins {
`kotlin-jvm`
`java-library`
`maven-publish`
id("com.tddworks.central-publisher") version "0.2.1-alpha"
}
group = "com.example"
version = "1.0.0"
java {
withJavadocJar()
withSourcesJar()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
}
centralPublisher {
// Credentials from environment variables (recommended)
credentials {
username = project.findProperty("SONATYPE_USERNAME")?.toString() ?: ""
password = project.findProperty("SONATYPE_PASSWORD")?.toString() ?: ""
}
// Project information
projectInfo {
name = "my-awesome-library"
description = "An awesome Kotlin library that does amazing things"
url = "https://github.com/myorg/my-awesome-library"
license {
name = "Apache License 2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
developer {
id = "myusername"
name = "My Name"
email = "me@example.com"
}
scm {
url = "https://github.com/myorg/my-awesome-library"
connection = "scm:git:git://github.com/myorg/my-awesome-library.git"
developerConnection = "scm:git:ssh://github.com/myorg/my-awesome-library.git"
}
}
// GPG signing
signing {
key = project.findProperty("SIGNING_KEY")?.toString() ?: ""
password = project.findProperty("SIGNING_PASSWORD")?.toString() ?: ""
}
// Publishing options
publishing {
autoPublish = false // Manual approval (safer)
dryRun = false // Set to true for testing
}
}
tasks.test {
useJUnitPlatform()
}
gradle.properties¶
# Project metadata
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
org.gradle.caching=true
org.gradle.parallel=true
kotlin.code.style=official
# Note: Never commit sensitive credentials to version control!
# Instead, use environment variables or global ~/.gradle/gradle.properties
settings.gradle.kts¶
rootProject.name = "my-awesome-library"
Setup with Interactive Wizard¶
The easiest way to configure everything is with the setup wizard:
./gradlew setupPublishing --console=plain
This will: 1. Auto-detect your project information 2. Guide you through credential setup 3. Generate the configuration automatically 4. Create GitHub Actions workflow (optional)
Environment Variables Setup¶
Set up your credentials securely using environment variables:
# Sonatype credentials
export SONATYPE_USERNAME=your-username
export SONATYPE_PASSWORD=your-central-token
# GPG signing key (export with: gpg --armor --export-secret-keys your-email@example.com)
export SIGNING_KEY="-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2
lQOYBGE...your-full-private-key-here...
-----END PGP PRIVATE KEY BLOCK-----"
export SIGNING_PASSWORD=your-gpg-password
Publishing Workflow¶
1. Validate Configuration¶
First, validate your setup without publishing:
./gradlew validatePublishing
Expected output:
> Task :validatePublishing
✅ Configuration validation successful
✅ Credentials verified
✅ GPG signing key validated
✅ Publications found: maven
✅ Ready to publish!
2. Create Bundle (Optional)¶
Create a deployment bundle to inspect before publishing:
./gradlew bundleArtifacts
This creates a ZIP file in build/central-portal/ containing all your artifacts in Maven repository format.
3. Publish to Central Portal¶
Upload your artifacts:
./gradlew publishToCentral
Expected output:
> Task :publishToCentral
📦 Creating deployment bundle...
✅ Bundle created: my-awesome-library-1.0.0-bundle.zip
🚀 Uploading to Central Portal...
✅ Upload successful!
📋 Deployment ID: 12345678-abcd-ef90-1234-567890abcdef
Visit https://central.sonatype.com/publishing/deployments to review and publish.
4. Manual Review and Publish¶
- Go to Central Portal
- Find your deployment by ID
- Review the artifacts
- Click "Publish" to release to Maven Central
Artifacts Generated¶
For a typical single-module project, the following artifacts are generated:
my-awesome-library-1.0.0.jar # Main JAR
my-awesome-library-1.0.0-sources.jar # Sources JAR
my-awesome-library-1.0.0-javadoc.jar # Javadoc JAR
my-awesome-library-1.0.0.pom # POM file
Each artifact includes:
- GPG signature (.asc file)
- MD5 checksum (.md5 file)
- SHA1 checksum (.sha1 file)
Common Issues and Solutions¶
"No publications found"¶
Make sure you have the required plugins:
plugins {
`java-library` // Required for Java publications
`maven-publish` // Required for publishing
}
"Sources JAR missing"¶
Ensure you generate source and javadoc JARs:
java {
withJavadocJar()
withSourcesJar()
}
"Invalid POM"¶
The plugin automatically generates a valid POM, but if you have custom maven-publish configuration, ensure it doesn't conflict:
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
// Don't override pom {} here - let the plugin handle it
}
}
}
"GPG signing failed"¶
Common GPG issues:
- Ensure your key includes full headers/footers
- Check that the key is not expired
- Verify the password is correct
- For gradle.properties, use \n for newlines:
SIGNING_KEY=-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v2\n\nlQOYBGE...\n-----END PGP PRIVATE KEY BLOCK-----
Testing Before Publishing¶
Use dry run mode to test your configuration:
centralPublisher {
publishing {
dryRun = true // Creates bundle but doesn't upload
}
}
Then run:
./gradlew publishToCentral
This will create the deployment bundle in build/central-portal/ without uploading to the portal.
Next Steps¶
- Set up CI/CD integration
- Learn about multi-module projects
- Explore Kotlin Multiplatform setup