Monday, March 20, 2017

Publishing Java Projects

Java doesn't seem to be going away any time soon. More so, as I think about service-oriented architectures, specifically microservice configurations and serverless approaches, Java stands firm as a mature, typed, easy-to-debug, easy-to-package, easy-to-share platform for developing cool (albeit backend) stuff.
What do I really like about Java? I think it's the build system, Maven. So much of what I build depends on a lot of shared stuff, and I take every bit of it for granted every time I click build. It only makes sense to give back.
It is at this point that I looked into publishing some core libraries I'm developing, which others might use to save time or solve issues. You would think publishing would be well understood and close to a one-click proposition. That's not what I found (at least with Maven). I know many have written up their experiences -- I've read a bunch -- but none completely described a simple happy path. Although I expect to update as I learn, I'm using this post to capture what I believe to be that path.
My focus here will be to follow the directions at sonatype.org for publishing to the "Central Repository", but filling in with less-than-obvious steps and shortcuts where helpful. They've published a video series that may help as well. Review their site for background.
When successful, your project should be public/searchable; making it available to anyone:


To publish, I will demonstrate the straight-forward path using Maven and GPG on a Windows development environment. I currently develop my java projects using Eclipse, but that shouldn't matter as long as you're working with a Maven project and have GPG installed. Get them here:

https://maven.apache.org/download.cgi
https://www.gnupg.org/download/index.en.html

Make sure your project builds with Maven, and that you have a version you're ready to publish for all to consume:

C:\>\Tools\Maven\bin\mvn clean install
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building StackedMachinery 1.0.0
[INFO] ------------------------------------------------------------------------
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 33.505 s
[INFO] Finished at: 2017-03-19T23:15:42-07:00
[INFO] Final Memory: 25M/261M
[INFO] ------------------------------------------------------------------------
C:\>

From here, we simply need to
  1. Set up a Sonatype publishing account,
  2. Generate and distribute a signing key,
  3. Add plugins to the project to generate required artifacts, and
  4. Deploy to Sonatype's Central Repository.
Once deployed (that is, pushed to a release repository for public consumption), the project will be available as a dependency for other projects. The project can be found via search after the Central Repository updates its indexes.
(1) Set Up a Sonatype Publishing Account

Click here to set up a new Sonatype Jira account. If you already have an account, log in with that instead. Do remember your credentials -- we'll use it again to log in to Sonatype's Nexus Repository Manager in step (4). Once created, visit here to submit a request to reserve your project's namespace (the maven group id you will use for your published projects). For one of my projects (com.unowmo.code.stacked-machinery), I submitted the following values:


The folks at Sonatype are very responsive, so you should expect prompt turn around of your requested group id. Wait for your jira issue to advance to "resolved" status before attempting to deploy.

Once resolved, we need to configure our Nexus Repository Manager account. Click here and log in with the same credentials you used to submit your group id jira request. Look for your "profile" (it may be accessed from your user name link in the upper right corner of the interface), then select "User Token" in the drop down menu currently showing "Summary":


If you don't see the "User Token" option (as was the case the first time I tried) you may need to wait for your account to update. Make sure your jira ticket request advanced to "resolved". Also try signing out and signing back in to reset the view.

Next, generate a user token and save the username and password values in your local Maven settings.xml file:

C:\>type C:\Users\Kirk\.m2\settings.xml
<settings>
    <servers>
        <server>
            <id>ossrh</id>
            <username>7a.....L</username>
            <password>BW.........B</password>
        </server>
    </servers>
</settings>
C:\>

You access the Central Repository staging servers with your user token as your credentials when you deploy via Maven. These settings allow you to deploy without including your token details in your project's pom.
(2) Generate and Distribute a Signing Key

Use GnuPG to sign your project artifacts during building. You can find background information on using GPG from Sonatype here. With GPG, first generate a signing key, then request to distribute it to a well-known key server:

C:\>gpg --version
gpg (GnuPG) 2.1.19
libgcrypt 1.7.6
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
...

C:\>gpg --gen-key
...

C:\>gpg --list-signatures
C:/Users/Kirk/AppData/Roaming/gnupg/pubring.kbx
-----------------------------------------------
pub   rsa2048 2017-03-14 [SC] [expires: 2019-03-14]
      A35....................................0
uid           [ultimate] Kirk Bulis 
sig 3        D3.............0 2017-03-14  Kirk Bulis 
sub   rsa2048 2017-03-14 [E] [expires: 2019-03-14]
sig          D3.............0 2017-03-14  Kirk Bulis 

C:\>
C:\>gpg --keyserver hkp://pool.sks-keyservers.net --send-keys D3.............0
gpg: sending key D3.............0 to hkp://pool.sks-keyservers.net

C:\>

There are interactive steps when generating a key that require you to set a passphrase to unlock the key from the local store. Remember your passphrase. You will use it each time you sign your project's artifacts during a build.

Once distributed to one of the accepted, well-known key servers, your key can be used to sign and deploy artifacts for release.
(3) Add Plugins to the Project to Generate Required Artifacts

The Central Repository does have requirements for publishing. These pertain to communicating relevant details to consumers of your components. Read the guide for explanations. My project uses the following pom entries; you may use it as a template:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <name>StackedMachinery</name>
   <groupId>com.unowmo.code.stacked-machinery</groupId>
   <artifactId>stacked-machinery</artifactId>
   <version>1.0.0</version>
   <packaging>jar</packaging>
   <description>Stacked state machinery with container-specific axion handling.</description>
   <url>https://github.com/unowmo/stacked-machinery</url>
   <licenses>
      <license>
         <name>MIT License</name>
         <url>https://opensource.org/licenses/mit-license.php</url>
      </license>
   </licenses>
   <developers>
      <developer>
         <name>Kirk Bulis</name>
         <email>kirk@unowmo.com</email>
         <organization>UNowMo, LLC</organization>
         <organizationUrl>http://unowmo.com</organizationUrl>
      </developer>
   </developers>
   <scm>
      <connection>scm:git:git://github.com/unowmo/stacked-machinery.git</connection>
      <developerConnection>scm:git:ssh://git@github.com:unowmo/stacked-machinery.git</developerConnection>
      <url>https://github.com/unowmo/stacked-machinery/tree/master</url>
   </scm>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   </properties>
   <distributionManagement>
      <snapshotRepository>
         <id>ossrh</id>
         <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
      </snapshotRepository>
   </distributionManagement>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5</version>
            <configuration>
               <source>1.5</source>
               <target>1.5</target>
            </configuration>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.6</version>
            <configuration>
               <archive>
                  <manifest>
                     <addDefaultImplementationEntries>false</addDefaultImplementationEntries>
                  </manifest>
                  <manifestEntries>
                     <Built-By>UNowMo, LLC</Built-By>
                  </manifestEntries>
               </archive>
            </configuration>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.1</version>
            <executions>
               <execution>
                  <id>attach-sources</id>
                  <goals>
                     <goal>jar-no-fork</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.4</version>
            <executions>
               <execution>
                  <id>attach-javadocs</id>
                  <goals>
                     <goal>jar</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>1.6</version>
            <executions>
               <execution>
                  <id>sign-artifacts</id>
                  <phase>verify</phase>
                  <goals>
                     <goal>sign</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <version>1.6.8</version>
            <extensions>true</extensions>
            <configuration>
               <serverId>ossrh</serverId>
               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
               <autoReleaseAfterClose>true</autoReleaseAfterClose>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>com.google.code.gson</groupId>
         <artifactId>gson</artifactId>
         <version>2.8.0</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
</project>

The Central Repository requires javadoc artifacts, and that all artifacts are signed using the key you distributed in step (3). These three plugins handle these tasks in your build:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
   ...
   <build>
      <plugins>
         ...
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.1</version>
            <executions>
               <execution>
                  <id>attach-sources</id>
                  <goals>
                     <goal>jar-no-fork</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.4</version>
            <executions>
               <execution>
                  <id>attach-javadocs</id>
                  <goals>
                     <goal>jar</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>1.6</version>
            <executions>
               <execution>
                  <id>sign-artifacts</id>
                  <phase>verify</phase>
                  <goals>
                     <goal>sign</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         ...
      </plugins>
   </build>
   ...
</project>

The nexus-staging-maven-plugin executes the task of pushing your components to a staging repository hosted by Sonatype, and then to a publicly-accessible release repository:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
   ...
   <distributionManagement>
      <snapshotRepository>
         <id>ossrh</id>
         <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
      </snapshotRepository>
   </distributionManagement>
   <build>
      <plugins>
         ...
         <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <version>1.6.8</version>
            <extensions>true</extensions>
            <configuration>
               <serverId>ossrh</serverId>
               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
               <autoReleaseAfterClose>true</autoReleaseAfterClose>
            </configuration>
         </plugin>
         ...
      </plugins>
   </build>
   ...
</project>

Note the configuration.server value of "ossrh". This links your configuration to the server entry in your local settings.xml file from step (1), which indicates to the plugin what credentials to use when accessing the staging and release repositories.

Test your build and install locally:

C:\>\Tools\Maven\bin\mvn clean install
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 1 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building StackedMachinery 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ stacked-machinery ---
[INFO] Deleting C:\...\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ stacked-machinery ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5:compile (default-compile) @ stacked-machinery ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to C:\...\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ stacked-machinery ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5:testCompile (default-testCompile) @ stacked-machinery ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\...\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ stacked-machinery ---
[INFO] Surefire report directory: C:\...\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.unowmo.machinery.tests.ModuleTest
Handling started
Layer (9550e204) of default following on started
(9550e204) state 'start' on 'started' -> 'ini01'
(9550e204) state 'ini01' on 'started' -> 'ini02'
(9550e204) state 'ini02' on 'started' -> 'pivot'
Handling testing
Layer (9550e204) of default following on testing
(9550e204) state 'pivot' on 'testing' -> 'tst01'
...
(9550e204) state 'tst04' on 'leaving' -> 'pivot'
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.574 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ stacked-machinery ---
[INFO] Building jar: C:\...\target\stacked-machinery-1.0.0.jar
[INFO]
[INFO] --- maven-source-plugin:3.0.1:jar-no-fork (attach-sources) @ stacked-machinery ---
[INFO] Building jar: C:\...\target\stacked-machinery-1.0.0-sources.jar
[INFO]
[INFO] --- maven-javadoc-plugin:2.10.4:jar (attach-javadocs) @ stacked-machinery ---
[INFO]
Loading source files for package com.unowmo.machinery...
Constructing Javadoc information...
Standard Doclet version 1.8.0_66
Building tree for all the packages and classes...
Generating C:\...\target\apidocs\com\unowmo\machinery\AxionTaskLibrary.html...
Generating C:\...\target\apidocs\com\unowmo\machinery\AxionTaskResolve.html...
...
Generating C:\...\target\apidocs\com\unowmo\machinery\class-use\AxionTaskLibrary.html...
Generating C:\...\target\apidocs\com\unowmo\machinery\package-use.html...
Building index for all the packages and classes...
Generating C:\...\target\apidocs\overview-tree.html...
Generating C:\...\target\apidocs\index-all.html...
Generating C:\...\target\apidocs\deprecated-list.html...
Building index for all classes...
Generating C:\...\target\apidocs\allclasses-frame.html...
Generating C:\...\target\apidocs\allclasses-noframe.html...
Generating C:\...\target\apidocs\index.html...
Generating C:\...\target\apidocs\help-doc.html...
[INFO] Building jar: C:\...\target\stacked-machinery-1.0.0-javadoc.jar
[INFO]
[INFO] --- maven-gpg-plugin:1.6:sign (sign-artifacts) @ stacked-machinery ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ stacked-machinery ---
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.jar to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.jar
[INFO] Installing C:\...\pom.xml to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.pom
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-sources.jar to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0-sources.jar
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-javadoc.jar to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0-javadoc.jar
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.jar.asc to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.jar.asc
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.pom.asc to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.pom.asc
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-sources.jar.asc to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0-sources.jar.asc
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-javadoc.jar.asc to C:\Users\Kirk\.m2\repository\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0-javadoc.jar.asc
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.403 s
[INFO] Finished at: 2017-03-20T18:58:47-07:00
[INFO] Final Memory: 32M/305M
[INFO] ------------------------------------------------------------------------

C:\>

A successful build indicates everything is in place to deploy. Otherwise, fixup the warnings (usually with missing javadoc comments in your code).
(4) Deploy to Sonatype's Central Repository

Deploying uses the local Maven settings.xml server configuration, the default GPG signing key, and the Sonatype nexus-staging-maven-plugin plugin to access and execute pushing your project's artifacts to a release repository. Use the following deploy command to execute this task:

C:\>\Tools\Maven\bin\mvn clean deploy
[INFO] Scanning for projects...
[INFO] Inspecting build with total of 1 modules...
[INFO] Installing Nexus Staging features:
[INFO]   ... total of 1 executions of maven-deploy-plugin replaced with nexus-staging-maven-plugin
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building StackedMachinery 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ stacked-machinery ---
[INFO] Deleting C:\...\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ stacked-machinery ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5:compile (default-compile) @ stacked-machinery ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to C:\...\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ stacked-machinery ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5:testCompile (default-testCompile) @ stacked-machinery ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\...\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ stacked-machinery ---
[INFO] Surefire report directory: C:\...\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.unowmo.machinery.tests.ModuleTest
...
...
[INFO]
[INFO] --- nexus-staging-maven-plugin:1.6.8:deploy (injected-nexus-deploy) @ stacked-machinery ---
[INFO] Performing local staging (local stagingDirectory="C:\...\target\nexus-staging\staging")...
[INFO]  + Using server credentials "ossrh" from Maven settings.
[INFO]  * Connected to Nexus at https://oss.sonatype.org:443/, is version 2.14.3-02 and edition "Professional"
[INFO]  * Using staging profile ID "5204........94" (matched by Nexus).
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.jar to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.jar
[INFO] Installing C:\...\pom.xml to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0.pom
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-sources.jar to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-javadoc.jar to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.jar.asc to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0
[INFO] Installing C:\...\target\stacked-machinery-1.0.0.pom.asc to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machinery-1.0.0
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-sources.jar.asc to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machine
[INFO] Installing C:\...\target\stacked-machinery-1.0.0-javadoc.jar.asc to C:\...\target\nexus-staging\staging\5204........94\com\unowmo\code\stacked-machinery\stacked-machinery\1.0.0\stacked-machine
[INFO] Performing remote staging...
[INFO]
[INFO]  * Remote staging into staging profile ID "5204........94"
[INFO]  * Created staging repository with ID "comunowmo-1007".
[INFO]  * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007
[INFO]  * Uploading locally staged artifacts to profile com.unowmo
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-javadoc.jar.asc
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-javadoc.jar.asc (499 B at 0.9 KB/sec)
Downloading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/maven-metadata.xml
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/maven-metadata.xml
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/maven-metadata.xml (330 B at 0.6 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.pom.asc
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.pom.asc (499 B at 4.0 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-sources.jar.asc
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-sources.jar.asc (499 B at 2.2 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-sources.jar
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-sources.jar (11 KB at 38.3 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-javadoc.jar
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0-javadoc.jar (62 KB at 107.8 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.jar.asc
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.jar.asc (499 B at 4.2 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.jar
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.jar (27 KB at 73.7 KB/sec)
Uploading: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.pom
Uploaded: https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/comunowmo-1007/com/unowmo/code/stacked-machinery/stacked-machinery/1.0.0/stacked-machinery-1.0.0.pom (4 KB at 12.6 KB/sec)
[INFO]  * Upload of locally staged artifacts finished.
[INFO]  * Closing staging repository with ID "comunowmo-1007".
Waiting for operation to complete...
.....
[INFO] Remote staged 1 repositories, finished with success.
[INFO] Remote staging repositories are being released...
Waiting for operation to complete...
.......
[INFO] Remote staging repositories released.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:06 min
[INFO] Finished at: 2017-03-20T19:42:52-07:00
[INFO] Final Memory: 39M/451M
[INFO] ------------------------------------------------------------------------

C:\>

The project is now deployed with the version specified in the project's pom. You can verify successful a release by browsing for your project in the Central Repository. For my project, I navigate to:

https://repo1.maven.org/maven2/com/unowmo/code/stacked-machinery/stacked-machinery/

to see latest. My latest releases are available there:

And that wraps up the simple path for publishing your java projects using Maven and GPG on Windows. Let me know your feedback through comments.
Follow Up

When discovering this approach to publishing, a couple of things came to mind that require fixing up in the future:
  1. The generated key sits in key pools managed by GPG. What are the best practices around reusing that same key in an additional environment (laptop, build machine, etc.)? How to keep it seamless?
  2. At the time of writing, it wasn't obvious how to secure the default signing key's passphrase in such a way as to keep it secure within each build environment. For now, I let the tool prompt during signing execution, which limits using this approach on automated environments (e.g., a build machine).
  3. What are some effective/cheap ways to market projects for use by a community?

No comments:

Post a Comment