Java Product Release Process

Java Product Release Process

This document describes the process that the Shibboleth team uses to package up and release a new version of our Java software products.

Release Environment

All our Java products use Maven to perform the actual build of release artifacts. Those artifacts are then uploaded to our Nexus installation at https://build.shibboleth.net/nexus.

The Javadoc artifacts are now managed somewhat separately but essentially as a follow-on step to the release, and no longer relies on the Maven “site” plugin and are built much faster and more reliably than before.

Translation Import

Before releasing a project that contains i18n artifacts, please check that the latest files from the corresponding folder tree in the java-idp-translations repository are imported into the project’s repository. See also https://shibboleth.atlassian.net/wiki/spaces/DEV/pages/1265631751.

Initial Configuration

Prior to performing any releases a few one-time configurations need to be done.

  1. Ensure that you have the proper data in your ~/.m2/settings.xml file.

  2. Generate an SSH key for both Git and Site deploys.

  3. Generate a PGP key and get it signed by the other developers. To avoid use of SHA-1 use the following in your gpg.conf file:

    personal-digest-preferences SHA512 cert-digest-algo SHA512 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
  4. Send the public SSH and PGP keys to committers email list with a request to be allowed to perform releases. 

A systems admin will then:

  1. Log in to Nexus and go the Security -> Users -> Add -> External User Role Mappingscreen

    1. Enter the user's LDAP uid as their user name (same userid they use for SVN)

    2. In the Role Management section, add the role Nexus Deployment and save the user account

  2. Add an account for you on the server, set your SSH key as an authorized key, and allow you to su to the Shibboleth website user.

    1. Add your key to the 'javasites' user, so that you can perform site releases. 

  3. Add your GPG key to the KEYS file on the download site

Parent POM Adjustment

In most cases, a major or minor release will involve tagging a new version of the parent POM and updating all projects to depend on it. The parent should not be updated for patch releases, this can cause Maven import confusion given that dependent projects (e.g. opensaml) will be referencing the older parent - see JPAR-175. Generally, for a given release, all projects should reference the same parent. If library updates are required for a patch release, you will need to override the dependencies in the appropriate project POMs. When in doubt, ask.

  1. Ensure that your working copy is in sync with the project repository (i.e., pull down any updates and commit any local changes).

  2. If not done, tag the parent POM to freeze the parent so it can be referenced by the subsequent steps.

    1. The tagging process for this is identical (bar the project and versions) to the release process described in the section below.

  3. Run the command java-parent-project/bin/lock-version-monolithic.sh (for a monolithic project} or java-parent-project/bin/lock-version-multimodule.sh (for a multi-module project). The arguments are the parent POM tag number, and the path to the project.

    # Lock java-shib-shared against tag version 17 of V5 parent java-parent-project/bin/lock-version-multimodule.sh 17 java-shib-shared
  4. After verifying the project's build using the newly referenced parent POM, commit the project changes.

Release Process

  1. Ensure you are using the correct Java version e.g. Amazon Corretto 17.

    1. If you are building the IdP, make sure you set MAVEN_HOME to the bin directory of your maven installation so the distribution-dependency-test runs correctly in idp-installer.

  2. Ensure that your working copy is in sync with the project repository (i.e., pull down any updates and commit any local changes). It can be useful to do this from scratch from a temporary folder, possibly inside a clean docker container. For example, into the temp directory, using a fresh maven repo location.

    # incase you get issues connecting to the GPG agent. export GPG_TTY=$(tty) # somewhere to store a fresh maven repo. If you want to preserve the transient release repo for archiving, etc, # use a permanent location for REPO, with the version in the name. export REPO=/tmp/repo cd /tmp git clone git@git.shibboleth.net:<project> cd <project> git checkout main
  3. Check that a non-snapshot version of maven-dist-enforcer and maven-dist-enforcer-data are used.

  4. Check the .check-m2 file is in the projects distribution project.

  5. Check the project builds, all the tests pass, and the artifacts are produced correctly (signed in their target directories):

    1. OPTIONALLY: If you want to manually inspect the signature report on the contents of the populated m2 directory, you need to use the install phase e.g.

      1. mvn -Dmaven.repo.local=$REPO -Prelease,sign clean install then vi target/m2SignatureReport.txt . This is automatically checked on deploy, so is not required.

  6. Set the project version number in the POM to the release version number using the command below. Also, ensure you update versions of any dependencies on our own projects that should be shipped with the release.

  7. Once satisfied, tag the release using a name equal to the version number of the release (e.g., 4.1.4 etc.) and ensure the POM at the tip of the branch being released NEVER contains a non-SNAPSHOT version number.

  8. Once tagged, set the project version number in the POM to the next SNAPSHOT increment.

  9. Add and commit the changes you made, and then push the tag.

  10. Checkout or export the tag to build the final release:

  11. After the build has been completed push the tag

  12. At this stage, DO NOT make any changes to fix errors without increasing the version again. This commits you to a release and you cannot go back.

  13. Mark the version as released in Jira.

Post Product Release

After releasing all projects, manually edit their POM files and update any first-party project dependencies to their next SNAPSHOT increment to unlock them..

Javadoc Release Process

So far as I know, this process does not require a separate repo, but it does assume you have variables defined for $MAVEN and $REPO to run, and as usual you have to be logged into the server for the Nexus deploy step to work.

Additionally, it will assume your SSH user name is $USER (from your shell) but may be overridden by setting $USERNAME.

A script can be run from the root of each project (where the individual project’s parent POM lives) to:

  1. Clean, and then build the “aggregate” javadoc for that project, which should show up in the target/ folder.

  2. Sign and upload the javadoc artifact to Nexus.

  3. SSH to the server and execute a loopback curl command to unpack the “latest” release version of the docs for a project to the right place and delete the SNAPSHOT javadoc from that version.

The script pulls all of the relevant settings from the pom.xml file in the directory from which it is run and will display them, and offer invididual “default-safe” prompts at each step to allow you to abort.

Note that while the script is largely idempotent, once an artifact is uploaded to Nexus, it won’t allow you to overwrite that, so once that step is done, you can’t start over without intervention.

Final Steps

  1. For top-level projects (IdP): Place the product distribution in the download section of the website by:

    1. Log in to the Shibboleth webserver

    2. Copy and rename the distribution archives and PGP signatures from the Nexus work directory to a temporary location e.g. your home directory

    3. Create SHA256 checksums for both the zip and tar file

    4. Create a suitable version-named directory on the download site and copy in the distribution, signatures, and checksums:

    5. Copy in the Windows installers (which are created separately) - note these are being sources from Rod’s home directory, so the path needs checking.

    6. Adjust the latest sym-link to point to the new version.

  2. For top-level projects:

    1. Update the relevant product's ReleaseNotes topic with the new release, the date, a link to a JIRA issue filter that produces the appropriate list of issues, and any important information about issues addressed, advisories, special requirements during upgrades, etc.

    2. Send an announcement to announce@shibboleth.net. Optionally sign the email with your PGP key.

    3. Update the "latest stable version" mentioned on the front page of the wiki space for the relevant product.

  3. For releases that include one or more Security Advisories:

    1. Finalize each advisory and fill in the date, double check any footnotes and URLs for correctness, and finalize the filename of the advisory based on the date and correct the self-referential link to the advisory in the text. See previous advisories for examples.

    2. Sign the advisory in text form with a PGP key that's in the project's PGP_KEYS file.

    3. Place the signed advisory on the server in /home/shibwww/html/community/advisories in a file named secadv_YYYYMMDD.txt and ensure appropriate ownership and 644 file mode.

    4. Send the PGP-signed advisory to announce@shibboleth.net (see previous examples in the archive).

    5. Update the relevant SecurityAdvisories page in the wiki space for an IdP advisory. The page includes a tabular display of all the advisories and links, and a table listing releases and how the advisories affect them.

Example using Docker

The attached script has been used to build a specific project inside the Shibboleth Docker Environment

Docker itself is started (this is on Windows) by this command

The %userprofile%\shibboleth-build-docker\user directory was configured as noted above and the the docker Docker Environment Documentation

Windows Installer

This is described separately forWiX3 and Wix4.

Releasing the “enforcer” plugins.

Our experience is that thinking through the implications of the build order of the enforcer plugins (java-mvn-enforcer, java-mvn-enforcer-data, java-mvn-enforcer-parent) is extra-ordinarily confusing. Although all that follows can be derived from first principals it is ‘very challenging’ and the following is offered as guidance so as to to avoid brain-melt

  • The three project (enforce, enforcer-data, enforcer-parent) are build in the same way as any other java project (with no javadoc)

  • If they do need to be release, then the release of enforcer and enforcer-data has to be

  • before the java-parent project.

  • In order to reduce circularity the enforcer projects have their own parent. This is a subset of the contents of the java-parent project.

  • This enforcer-parent-project does have references to enforcer and enforcer-data versions, and because circularity remains it is important to follow the guidance below

    • The enforcer and enforcer-data project must NEVER have a parent with a SNAPSHOT version.

    • By extension, this means that the enforcer parent project is release AFTER the enforcer or enforcer-data project

A typical build would be

  • Release java-mvn-enforcer-data (shall we say version ‘d' and parent version 'p’)

  • Release java-parent

  • Release the rest of the Java stack

  • Soon (but not immediately) release enforcer-parent version p+1

    • Update any dependencies from java-parent (including the latest enforcer and enforcer data)

    • Do a standard release of the parent project

    • Update enforcer and enforcer-data to be parented by version p+1

    • IMMEDIATELY run a complete (m2 checking) build (of each project).
      There should not be an issue (because there is nothing in enforcer-parent that is not in java-parent) but if there is you need to

      • Revert the parent of enforcer data to be version 'p'

      • Fix the problem,

      • Re-release enforcer-data

      • Point enforcer-parent to this version and start again with the release of parent version p+2