sbt publish
Synopsis
sbt
[query / ] publish
sbt
[query / ] publishSigned
sbt
[query / ] publishLocal
sbt
[query / ] publishM2
Description
The publish family of tasks provide means for compiling and publishing your project. Publishing in this context consists of uploading a descriptor, such as a Maven POM or ivy.xml
, and artifacts, such as a JAR or war
file, to a repository so that other projects can specify your project as a dependency.
- The
publish
task publishes your project to a remote repository, such as JFrog Artifactory or Sonatype Nexus instance. - The
publishSigned
task, enabled using sbt-pgp plugin, is used to publish GPG-signed artifacts. - The
publishLocal
task publishes your project to the Ivy local file repository, which is usually located at$HOME/.ivy2/local/
. You can then use this project from other projects on the same machine. - The
publishM2
task publishes your project to the local Maven repository.
There's a specific recipe for publishing to the Central Repo.
Skip publishing
To avoid publishing a project, add the following setting to the subprojects that you want to skip:
publish / skip := true
Common use case is to prevent publishing of the root project.
Define the repository
To specify the repository, assign a repository to publishTo
and optionally set the publishing style. For example, to upload to Nexus:
publishTo := Some("Sonatype Snapshots Nexus" at "https://oss.sonatype.org/content/repositories/snapshots")
To publish to a local maven repository:
publishTo := Some(MavenCache("local-maven", file("path/to/maven-repo/releases")))
To publish to a local Ivy repository:
publishTo := Some(Resolver.file("local-ivy", file("path/to/ivy-repo/releases")))
If you're publishing the Central Repository, you will also have to select the right repository depending on your artifacts: SNAPSHOT versions go to the central-snapshots repository while other versions go to the local staging repository. Doing this selection can be done by using the value of the version
setting:
publishTo := {
val centralSnapshots = "https://central.sonatype.com/repository/maven-snapshots/"
if version.value.endsWith("-SNAPSHOT") then Some("central-snapshots" at centralSnapshots)
else localStaging.value
}
Publishing locally
The publishLocal
task will publish to the "local" Ivy repository. By default, this is at $HOME/.ivy2/local/
. Other builds on the same machine can then list the project as a dependency. For example, if the project you are publishing has configuration parameters like:
organization := "com.example"
version := "0.1-SNAPSHOT"
name := "hello"
Then another build on the same machine can depend on it:
libraryDependencies += "com.example" %% "hello" % "0.1-SNAPSHOT"
The version number you select must end with SNAPSHOT
, or you must change the version number each time you publish to indicate that it's a changing artifact.
Generally the use of SNAPSHOT dependencies should be avoided beyond testing on a single machine since it makes dependency resolution slower and the build non-repeatable.
Similar to publishLocal
, publishM2
task will publish the user's Maven local repository. This is at the location specified by $HOME/.m2/settings.xml
or at $HOME/.m2/repository/
by default. Another build would require Resolver.mavenLocal
to resolve out of it:
resolvers += Resolver.mavenLocal
Credentials
There are two ways to specify credentials for such a repository.
The first and better way is to load them from a file, for example:
credentials += Credentials(Path.userHome / ".sbt" / ".credentials")
The credentials file is a properties file with keys realm
, host
, user
, and password
. For example:
realm=Sonatype Nexus Repository Manager
host=my.artifact.repo.net
user=admin
password=admin123
The second way is to specify them inline:
credentials += Credentials("Sonatype Nexus Repository Manager", "my.artifact.repo.net", "admin", "admin123")
Credentials matching is done using both: realm
and host
keys. The realm
key is the HTTP WWW-Authenticate
header's realm directive, which is part of the response of HTTP servers for HTTP Basic Authentication. For a given repository, this can be found by reading all the headers received. For example:
curl -D - my.artifact.repo.net
Cross-publishing
To support multiple incompatible Scala versions, use projectMatrix and publish (see Cross building setup).
Overriding the publishing convention
By default sbt will publish your artifact with the binary version of Scala you're using. For example if your project is using Scala 2.13.x your example artifact would be published under example_2.13
. This is often what you want, but if you're publishing a pure Java artifact or a compiler plugin you'll want to change the CrossVersion
. See the Cross building setup page for more details under the Publishing convention section.
Published artifacts
By default, the main binary JAR, a sources JAR, and a API documentation JAR are published. You can declare other types of artifacts to publish and disable or modify the default artifacts. See the Artifact page for details.
Version scheme
versionScheme
setting tracks the version scheme of the build:
versionScheme := Some("early-semver")
The supported values are "early-semver"
, "pvp"
, "semver-spec"
, and "strict"
. sbt will include this information into pom.xml
and ivy.xml
as a property.
Some("early-semver")
: Early Semantic Versioning that would keep binary compatibility across patch updates within 0.Y.z (for instance 0.13.0 and 0.13.2). Once it goes 1.0.0, it follows the regular Semantic Versioning where 1.1.0 is bincompat with 1.0.0.Some("semver-spec")
: Semantic Versioning where all 0.y.z are treated as initial development (no bincompat guarantees).Some("pvp")
. Haskell Package Versioning Policy where X.Y are treated as major version.Some("strict")
. Requires exact match of version.
This information will be annotated into the pom.xml
file, which helps downstream projects determine whether a version conflict is safe to resolve or not. See Preventing version conflicts with versionScheme (2021).
Modifying the generated POM
When publishMavenStyle
is true
, a POM is generated by the makePom
action and published to the repository instead of an Ivy file. This POM file may be altered by changing a few settings. Set pomExtra
to provide XML (scala.xml.NodeSeq
) to insert directly into the generated pom. For example:
pomExtra := <something></something>
There is also a pomPostProcess
setting that can be used to manipulate the final XML before it is written. It's type is Node => Node
.
pomPostProcess := { (node: Node) =>
....
}
makePom
adds to the POM any Maven-style repositories you have declared. You can filter these by modifying pomRepositoryFilter
, which by default excludes local repositories. To instead only include local repositories:
pomIncludeRepository := { (repo: MavenRepository) =>
repo.root.startsWith("file:")
}