This guide covers how to configure your project for publishing, generate POM files, and publish artifacts to repositories.
Basic Publishing Configuration
Configure the essential metadata for publishing:
organization := "com.example"
name := "my-library"
version := "1.0.0"
// Project metadata
description := "A useful Scala library"
licenses := Seq ( "Apache-2.0" -> url( "https://www.apache.org/licenses/LICENSE-2.0" ))
homepage := Some (url( "https://github.com/example/my-library" ))
// SCM information
scmInfo := Some (
ScmInfo (
url( "https://github.com/example/my-library" ),
"scm:[email protected] :example/my-library.git"
)
)
// Developers
developers := List (
Developer (
id = "johndoe" ,
name = "John Doe" ,
email = "[email protected] " ,
url = url( "https://github.com/johndoe" )
)
)
These metadata fields are included in the generated POM file and displayed on Maven Central.
Publishing Style
Choose between Maven and Ivy publishing:
// Maven-style publishing (recommended for most projects)
publishMavenStyle := true
// Ivy-style publishing
publishMavenStyle := false
Use Maven-style publishing (publishMavenStyle := true) for publishing to Maven Central or other Maven repositories.
Publish Destination
Configure where to publish:
Maven Central via Sonatype
Custom Nexus Repository
File-based Repository
Local Publishing Only
publishTo := {
val nexus = "https://s01.oss.sonatype.org/"
if (isSnapshot.value)
Some ( "snapshots" at nexus + "content/repositories/snapshots" )
else
Some ( "releases" at nexus + "service/local/staging/deploy/maven2" )
}
Publishing Tasks
sbt provides several publishing tasks:
# Publish to the repository defined in publishTo
sbt publish
# Publish to local Ivy repository (~/.ivy2/local)
sbt publishLocal
# Publish to local Maven repository (~/.m2/repository)
sbt publishM2
# Generate POM file only
sbt makePom
Test locally
Publishes to your local Ivy cache for testing.
Test with Maven
Publishes to your local Maven repository.
Publish to remote
Publishes to the configured remote repository.
Credentials
Configure credentials for publishing to private repositories:
Inline Credentials
From File
From Environment
credentials += Credentials (
"Sonatype Nexus Repository Manager" ,
"s01.oss.sonatype.org" ,
"username" ,
"password"
)
Credentials file format:
~/.sbt/sonatype_credentials
realm =Sonatype Nexus Repository Manager
host =s01.oss.sonatype.org
user =your-username
password =your-password
POM Customization
Add custom XML to the generated POM:
pomExtra :=
< properties >
< info .apiURL > https :// api.example.com </ info .apiURL >
</ properties >
POM Post-Processing
Transform the generated POM:
import scala . xml . _
import scala . xml . transform . _
pomPostProcess := { ( node : Node ) =>
new RuleTransformer ( new RewriteRule {
override def transform ( node : Node ) : Seq [ Node ] = node match {
case e : Elem if e.label == "dependency" &&
(e \\ "groupId" ).text == "bad-dependency" =>
NodeSeq . Empty
case _ => node
}
}).transform(node).head
}
Repository Filtering
Control which repositories appear in the POM:
// Include all repositories
pomAllRepositories := true
// Filter repositories
pomIncludeRepository := { repo : MavenRepository =>
repo.root.startsWith( "https://" )
}
Be careful when including custom repositories in published POMs as it can affect dependency resolution for users.
Publishing Artifacts
Control What Gets Published
// Publish main artifact
Compile / packageBin / publishArtifact := true
// Publish test artifact
Test / packageBin / publishArtifact := false
// Publish sources
Compile / packageSrc / publishArtifact := true
// Publish documentation
Compile / packageDoc / publishArtifact := true
Custom Artifacts
Define custom artifacts to publish:
artifacts ++= Seq (
Artifact (
name = "my-library" ,
`type` = "zip" ,
extension = "zip" ,
classifier = "assets"
)
)
packagedArtifacts += {
val assetsZip = ( Compile / target).value / "my-library-assets.zip"
// Create the zip...
artifacts.value.head -> assetsZip
}
Cross-Publishing
Publish for multiple Scala versions:
crossScalaVersions := Seq ( "2.13.12" , "3.3.1" )
# Publish for all Scala versions
sbt +publish
# Publish locally for all versions
sbt +publishLocal
# Publish for specific version
sbt ++2.13.12 publish
sbt Plugin Publishing
For sbt plugins, additional configuration is needed:
sbtPlugin := true
// The sbt version to compile against
pluginCrossBuild / sbtVersion := "2.0.0-M2"
// Publish legacy Maven-style (for compatibility)
sbtPluginPublishLegacyMavenStyle := true
# Publish plugin for multiple sbt versions
sbt +publish
Signing Artifacts
Sign your artifacts for publishing to Maven Central:
addSbtPlugin( "com.github.sbt" % "sbt-pgp" % "2.2.1" )
# Use PGP key from keyring
sbt publishSigned
# Or configure key
sbt set Global / usePgpKeyHex ( "DEADBEEF" )
Maven Central requires signed artifacts. Use sbt-pgp plugin for signing.
Staging and Release
For Sonatype/Maven Central, use a staging workflow:
addSbtPlugin( "org.xerial.sbt" % "sbt-sonatype" % "3.10.0" )
addSbtPlugin( "com.github.sbt" % "sbt-pgp" % "2.2.1" )
# Publish signed artifacts to staging
sbt publishSigned
# Close and release staging repository
sbt sonatypeBundleRelease
Version Management
Snapshot Versions
version := "1.0.0-SNAPSHOT"
isSnapshot := version.value.endsWith( "-SNAPSHOT" )
Snapshots are published to snapshot repositories and can be overwritten.
Release Versions
Release versions are immutable once published to Maven Central.
Version Scheme
Declare your versioning scheme:
versionScheme := Some ( "early-semver" )
// Options: "early-semver", "pvp", "semver-spec", "strict"
Declaring versionScheme helps dependency resolution understand version compatibility.
Publishing Workflow
Configure metadata
Set all required fields: organization, name, version, licenses, developers, scmInfo.
Configure credentials
Add credentials for your target repository.
Set publish destination
Configure publishTo for your repository.
Sign artifacts (for Maven Central)
Use sbt-pgp to sign your artifacts.
Best Practices
Complete metadata
Always provide complete metadata: organization, licenses, SCM info, and developers.
Use semantic versioning
Follow semantic versioning and declare your versionScheme.
Publish sources and docs
Always publish source and documentation JARs for better IDE integration.
Test before publishing
Use publishLocal or publishM2 to test your artifacts before publishing.
Keep credentials secure
Store credentials in files outside your repository or use environment variables.
Sign releases
Sign all release artifacts, especially for Maven Central.
Cross-publish libraries
For libraries, publish for multiple Scala versions using crossScalaVersions.