How to do Maven release builds from DEV@cloud to central

Stephen Connolly's picture

NewImage

How to do Maven release builds from DEV@cloud to central</

The holy grail of Jenkins jobs building Maven projects is the push button release build. If you want to do this on DEV@cloud, this post will let you in on all the tricks that you need to follow to make it all happen.

Keeping things secret

When cutting release builds from any CI server there are some things that you need to put on the CI server.

In order to push releases to central you will need to have your artifacts signed with a GPG key, thus you will need to give your CI server the GPG private key and the passphrase for the GPG private key. If you are not happy giving your CI server a GPG key that Sonatype have configured oss.sonatype.org to accept, then stick to cutting release builds from your desktop.

In order to push releases to central you will need to give Maven a username and password for pushing the artifacts to oss.sonatype.org. Again if you are not happy giving your CI server these details then stick to cutting release builds from your desktop.

We don’t want people to be able to see these files via the Jenkins UI, so we will store these secrets on your CloudBees /private WebDAV share (and we will cringe at the CloudBees UI that calls these WebDAV shares “Maven repositories” when we all know they are no such thing… but that is another story… they are just perfect for what we need).

So connect to your /private WebDAV share and create a folder to hold a settings.xml file and a .gnupg directory.

 

Screen Shot 2014 02 25 at 22 49 56

Here is one I created for anyone following along.

The release settings

The settings.xml is going to be somewhat bare bones:

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">


cloudbees-oss-snapshots
********
********


cloudbees-oss-staging
********
********




cloudbees-oss-release

4A2F92BB
********
false
true
never
/private/cloudbees/central-release/.gnupg
/private/cloudbees/central-release/.gnupg/pubring.gpg
/private/cloudbees/central-release/.gnupg/secring.gpg



Now obviously I have masked all the passwords. I didn’t mask our gpg keyname as anyone checking our OSS releases on central will be verifying that the GPG key has that hex signature anyway and more importantly to illustrate that it is the hex signature of the key that is required and not some other human readable key name that you may have assigned to the key.

It is important that you specify a lockMode of never as the /private WebDAV share is mounted read only on the DEV@cloud slaves. The mount point path will be /private/{your DEV@cloud account name}/ In our case the account name we are using for this example is cloudbees.

Note:

When you have developers working on different OSS projects, they will thank you if you use a unique name for your server IDs and your release profile. In our case we are using two server IDs: cloudbees-oss-snapshots and cloudbees-oss-staging and our release profile is called cloudbees-oss-release. The reason for doing this is so that if I have to cut a release from my laptop for some reason or other I can have everything setup in a settings.xml that also includes profiles for our own internal closed source release, Jenkins plugin releases, Apache Maven releases as well as other OSS projects that I work on. I thus can have one single settings.xml that I just use all the time. If we used the default server ids and release profile id configured by Sonatype’s oss-parent pom then I would have to keep swapping settings.xml files to cut releases of different projects… which is a nighmare!

The (parent) pom

Now the next step is to make sure that our pom.xml file is setup right for a release. Here is the oss parent pom that we use:


4.0.0
  com.cloudbees
cloudbees-oss-parent
pom
4
...
  
2.2.1
...


cloudbees-oss-snapshots
Sonatype Nexus Snapshots
${sonatypeOssDistMgmtSnapshotsUrl}


cloudbees-oss-staging
Nexus Release Repository
https://oss.sonatype.org/service/local/staging/deploy/maven2/

  

cloudbees-oss-snapshots
Sonatype Nexus Snapshots
https://oss.sonatype.org/content/repositories/snapshots

false


true


  
UTF-8
UTF-8
UTF-8
https://oss.sonatype.org/content/repositories/snapshots/
git

  


maven-enforcer-plugin


enforce-maven

enforce




(,2.1.0),(2.1.0,2.2.0),(2.2.0,)
Maven 2.1.0 and 2.2.0 produce incorrect GPG signatures and checksums respectively.


(,3.0),[3.0.4,)
Maven 3.0 through 3.0.3 inclusive do not pass correct settings.xml to Maven Release Plugin.









...

maven-enforcer-plugin
1.3.1


maven-gpg-plugin
1.5

...

maven-release-plugin
2.4.2

forked-path
false
${arguments} -Pcloudbees-oss-release

${git.provider}




org.apache.maven.scm
maven-scm-provider-jgit
1.9


org.apache.maven.scm
maven-scm-provider-gitexe
1.9



...


  

cloudbees-oss-release



maven-source-plugin


attach-sources

jar-no-fork





maven-javadoc-plugin


attach-javadocs

jar





maven-gpg-plugin


sign-artifacts
verify

sign







Most of this is just lifted from Sonatype’s oss-parent with a change of server IDs and the release profile name. I also added an extra enforcer rule to ensure that we have a version of Maven that will allow us to pass the effective settings.xml through to the forked Maven process that the release plugin invokes to do the release work.

The Jenkins job

First off. Please do not do release builds with a Maven project type job. The Jenkins Maven project type does not and cannot instrument the forked Maven process so all the integrations that it provides will either be capturing the wrong artifacts / test results or no artifacts / test results. In short, you are better off with a FreeStyle project with a Maven build step (or a literate style project).

The key part of the job configuration is as follows:

Screen Shot 2014 02 25 at 23 27 31

You need to ensure that the private WebDAV share is mounted.

In our case our source code for this project is hosted on GitHub, so we use the SSH Agent plugin to ensure that the Maven release plugin has a SSH key that can push to the GitHub project.

Finally we ensure that the settings.xml file is the one from the private WebDAV share.

Note: if you really insist on using the Maven job type, you can use an analogous configuration… it will however add a layer of complexity to your build.

Now try a build

At this point you should have your Jenkins job ready to go… so why not try a build…

Screen Shot 2014 02 25 at 23 34 44

Hopefully you too will get the final Finished: SUCCESS of such a build.

Extra finesses

There are some finesses you can add:

  1. Make the build parameterised so that you don’t cut a release by accident

     Screen Shot 2014 02 25 at 23 36 46

  2. Use Sonatype’s staging plugins to close the staging repository at the end of the release

Summary

It’s not too hard when you know what to do. Most of the tricks are around ensuring that you have the correct versions of the GPG and Release plugins so that your custom settings.xml can be used and the GNUPGHOME can function when on a read-only filesystem… 

Hopefully this post has made your quest a lot easier to complete

- Stephen Connolly

Blog Categories: 

Comments

Hello, I'm following this guide and I get this error: gpg: fatal: can't create `/private/account-id/.gnupg/trustdb.gpg': Permission denied Do you know why this is happening?

Add new comment