Deploying and releasing artifacts

Maven · Advanced · 12 min

Sharing libraries across teams and publishing to Maven Central is a core Maven workflow.

mvn deploy uploads the artifact, its POM and attached artifacts (sources, javadoc) to the repository in <distributionManagement>. Credentials come from a <server> in settings.xml whose <id> matches.

Snapshots vs releases:

  • A -SNAPSHOT version can be deployed repeatedly; each upload gets a timestamp and consumers re-check for newer ones (daily by default, -U forces an update). Snapshot repositories are for ongoing work.
  • A release version is immutable; repositories reject re-uploads. Releases must not depend on snapshots (the enforcer's requireReleaseDeps checks this).

Releasing means: set the release version, tag, build and deploy, then bump to the next snapshot. Tools:

  • versions:set -DnewVersion=1.3.0 and versions:commit, scripted in CI; with ${revision} CI-friendly versions you simply pass -Drevision=1.3.0 and use the flatten plugin so the deployed POM has a concrete version.
  • maven-release-plugin (release:prepare and release:perform) automates the tag-and-bump cycle, with more ceremony.

Maven Central publishing goes through Sonatype's Central Portal (central-publishing-maven-plugin) and requires a verified namespace, source and javadoc jars (maven-source-plugin, maven-javadoc-plugin), full POM metadata (name, description, url, license, developers, scm) and GPG signatures (maven-gpg-plugin).

Attach sources with the jar-no-fork goal so they're deployed alongside the main jar. Never deploy from a dirty working tree or with local uncommitted changes.

Example

<distributionManagement>
  <repository>
    <id>nexus</id>                                  <!-- matches <server id="nexus"> in settings.xml -->
    <url>https://nexus.acme.com/repository/maven-releases/</url>
  </repository>
  <snapshotRepository>
    <id>nexus</id>
    <url>https://nexus.acme.com/repository/maven-snapshots/</url>
  </snapshotRepository>
</distributionManagement>

<build>
  <plugins>
    <plugin>
      <artifactId>maven-source-plugin</artifactId>
      <version>3.3.1</version>
      <executions>
        <execution><id>sources</id><goals><goal>jar-no-fork</goal></goals></execution>
      </executions>
    </plugin>
  </plugins>
</build>

<!-- Snapshot:  mvn deploy                       (1.3.0-SNAPSHOT, repeatable)
     Release:   mvn versions:set -DnewVersion=1.3.0 && mvn versions:commit
                mvn -DskipTests deploy && git tag v1.3.0
                mvn versions:set -DnewVersion=1.4.0-SNAPSHOT
     or with CI-friendly versions: mvn -Drevision=1.3.0 deploy -->

Remember

  • mvn deploy uploads to distributionManagement using settings.xml credentials
  • Snapshots are mutable and re-checked; releases are immutable
  • Release = set version, tag, deploy, bump to next snapshot
  • Central requires sources, javadoc, POM metadata and GPG signatures

Watch out for

  • Releasing a version that still depends on a -SNAPSHOT library, which later disappears or changes.

Check yourself

  1. Why does a repository reject a second mvn deploy of version 1.3.0?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: maven.apache.org/plugins/maven-deploy-plugin/