Using Maven to Release a Plugin

How to use Maven to release a commercial plugin for Jenkins to ToolSpring Update Center.

Using Maven to Release a Plugin

This guide is based on the Maven Release Plugin which automates the steps to release artifacts to the ToolSpring Update Center. See article Releasing a Commercial Plugin for background information about releasing to this Update Center.

sample-jenkins-plugin-maven is a sample Jenkins Plugin project with a Maven configuration for releasing to ToolSpring.

You will need the following installed:

  • Apache Maven
  • Java JDK 1.8 which is required for compatibility with Jenkins.

If you are starting a Jenkins plugin project or don't have a Maven configuration, i.e. Project Object Model (POM, pom.xml file), then Maven Archetype can generate much of the required boilerplate for you. The command below will prompt you for the specific details of your project, then generate a pom.xml file and hierarchy of subdirectories.

On Linux:

mvn archetype:generate -Dfilter=io.jenkins.archetypes:

On Windows:

mvn archetype:generate "-Dfilter=io.jenkins.archetypes:"

Create or move your project code and resource files into the appropriate subdirectories.

You may need to edit your Maven configuration to include the XML tags described below. These tags are all child tags of project, the root tag.

Configuration: Parent POM

This parent POM is required to build a binary artifact compatible with Jenkins, i.e. hpi/jpi file.

If your pom.xml file does not already include it, copy the parent tag below into the file. You may need to set a different value for the version child tag.

<project>
    ...
    <parent>
        <groupId>org.jenkins-ci.plugins</groupId>
        <artifactId>plugin</artifactId>
        <version>3.4</version>
        <relativePath />
    </parent>
    ...
</project>

Configuration: Artifact Identity

The tags below describe your plugin. If your pom.xml file does not already include any of these tags, copy them into the file. Set the values at groupId, artifactId, version, and name to the corresponding values for your plugin.

<project>
    ...
    <groupId>com.my-domain.plugins</groupId>
    <artifactId>my-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>My Plugin</name>
    <packaging>hpi</packaging>
    ...
</project>

Note: The value at version should specify a snapshot version like 1.0-SNAPSHOT. During the relase process the Maven Release Plugin will automatically change this value to its release form, i.e. 1.0 in this example.

Configuration: Properties

If your pom.xml file does not already include them, copy the jenkins.version and java.level tags below into the file (note they are child tags of the properties tag). You may need to change the value of jenkins.version, which specifies the minimum Jenkins version for compatibility with your plugin.

<project>
    ...
    <properties>
        ...
        <!-- Baseline Jenkins version you use to build the plugin. Users must have this version or newer to run. -->
        <jenkins.version>2.277.1</jenkins.version>
        <java.level>8</java.level>
        ...
    </properties>
    ...
</project>

Note: During a build, Maven will download Jenkins libraries that correspond to the specified version of Jenkins.

Configuration: SCM

The Maven Release Plugin expects your project to be in a source control repository, e.g. Git or Subversion. If your pom.xml file does not already include it, copy the scm tag below into the file. Set the values at connection, developerConnection, and url to the corresponding URLs for your source control repository.

<project>
    ...
    <scm>
        <connection>scm:git:git@github.com:my-github-name/my-plugin.git</connection>
        <developerConnection>scm:git:git@github.com:my-github-name/my-plugin.git</developerConnection>
        <url>https://github.com/my-github-name/my-plugin</url>
    </scm>
    ...
</project> 

The URL at developerConnection should allow Write access; the Maven goal release:prepare (see below) will push changes to this location.

If your connection URLs have the prefix scm:git:https:// then Maven will prompt you to enter your login credentials for the SCM remote host. You can skip this prompt and authenticate non-interactively if these login credentials are the same as for ToolSpring. The configuration property below directs Maven to use your ToolSpring login credentials stored in a Maven parameters file (see below, section Authenticating to the Update Center).

<properties>
    ...
    <project.scm.id>toolspring-licensing-service</project.scm.id>
    ...
</properties>

Configuration: Distribution Management

Copy the distributionManagement tag below into your pom.xml file. The release process will push your plugin artifacts to the specified repository.

<project>
    ...
    <distributionManagement>
        <repository>
            <id>toolspring-licensing-service</id>
            <url>https://licensing.toolspring.com/repository/toolspring-releases/</url>
        </repository>
    </distributionManagement>
    ...
</project>

Authenticating to the Update Center

You may use a Maven parameters file, conventionally named settings.xml, to store your ToolSpring login credentials. Be sure to keep the file secure when it contains secrets like this; for example, do not include the file in source control. For the purposes of a release you may use one of the options listed below:

  • A parameters file in any secure location that is convenient.
  • The Maven user parameters file, usually located in the .m2 subdirectory of your home directory; see the table below.
Operating systemPath
Linux~/.m2/settings.xml
Windows%USERPROFILE%\.m2\settings.xml

Copy the text below to your parameters file. Set the values at username and password to your ToolSpring login credentials.

<?xml version="1.0" encoding="UTF-8"?>
<settings>
    <servers>
        <server>
            <id>toolspring-licensing-service</id>
            <username>my-username</username>
            <password>my-password</password>
        </server>
    </servers>
</settings>

Using Maven Release Plugin

There are two main steps involved in using the Release Plugin: the Maven goals release:prepare and release:perform. Before executing these steps, be sure that your local source code repository has no uncommitted changes.

Prepare: Execute Maven to prepare the release as in the example command below, where the current directory is the project root directory. The --batch-mode option specifies that the command should execute non-interactively, using the default values defined in the pom.xml file.

mvn --batch-mode release:prepare

Perform: If the above command succeeds, execute Maven to perform the release. In the example command below, the current directory is the plugin source project directory, and the --settings option specifies a Maven parameters file in a separate directory.

mvn release:perform --settings ~/local/secrets/ToolSpring/settings.xml

Alternately, the command below implicitly uses the Maven user parameters file:

mvn release:perform

If the release:perform command succeeds then its execution log should end with lines similar to the example below:

...
[INFO] Cleaning up after release...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  36.244 s
[INFO] Finished at: 2021-04-12T23:22:07+10:00
[INFO] ------------------------------------------------------------------------

The sections below describe common errors and possible causes.

Error: SCM Authentication with Login Credentials

The release:prepare command may log output similar to this:

...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:prepare (default-cli) on project delta-static-analysis: Unable to commit files
[ERROR] Provider message:
[ERROR] The git-push command failed.
[ERROR] Command output:
[ERROR] remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
[ERROR] remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
[ERROR] fatal: Authentication failed for 'https://github.com/aprozorov/delta-static-analysis-plugin.git/'

In this example the POM configuration value at project.scm.developerConnection has the prefix scm:git:https://, therefore Maven will authenticate to the remote host using your login credentials, i.e. username and password/personal access token.

Possible causes of the error:

  • The pom.xml file does not include a property project.scm.id whose value matches server.id in the Maven parameters file.
  • Maven parameters file exists but the value of server.id does not match distributionManagement.repository.id in the pom.xml file.
  • Maven parameters file exists but the values of server.username or server.password are incorrect for the specified code repository.
  • Maven parameters file exists but the value of server.password is not the expected personal access token for the remote host.

Note: If your Maven parameters file does not exist, or does not include your SCM login credentials, Maven will prompt you to enter these credentials interactively. However, the next command release:perform will fail because it requires username and password for authenticating to the Update Center as well as your SCM.

Error: SCM Authentication with SSH

The release:perform command may log output similar to this:

...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:perform (default-cli) on project delta-static-analysis: Unable to checkout from SCM
[ERROR] Provider message:
[ERROR] The git-clone command failed.
[ERROR] Command output:
[ERROR] Cloning into '/home/aprozorov/local/src/jenkins/plugins/maven/delta-static-analysis-plugin/target/checkout'...
[ERROR] git@github.com: Permission denied (publickey).
[ERROR] fatal: Could not read from remote repository.
[ERROR]
[ERROR] Please make sure you have the correct access rights
[ERROR] and the repository exists.

The Maven configuration value at project.scm.connection has either of the prefixes listed below:

  • scm:git:git@
  • scm:git:ssh:

In this case Maven will use SSH when authenticating to the remote host. Possible causes of the error:

  • An SSH agent is not running.
  • The SSH private key identity has not been added to the SSH agent.

Error: Previously Released Version

The Update Center will not accept a release version that is already hosted there. An attempt to replace a hosted version will cause the release:perform command to fail.

However it is more likely that the previous step release:prepare will fail in this case, with log output similar to this:

...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  59.727 s
[INFO] Finished at: 2021-09-16T16:25:46+10:00
[INFO] ------------------------------------------------------------------------
[INFO] 1 goals, 1 executed
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:prepare (default-cli) on project delta-static-analysis: Unable to tag SCM
[ERROR] Provider message:
[ERROR] The git-tag command failed.
[ERROR] Command output:
[ERROR] fatal: tag 'delta-static-analysis-1.7' already exists

In this case a tag matching the project version was previously created in the remote SCM repository.

Possible causes of the error:

  • A previous execution of release:prepare failed, and was unable to update the pom.xml file as usual.
    • The command release:rollback may resolve the problem.
    • Otherwise you will need to edit the pom.xml file to correct the values of version and/or scm.tag. Then execute release:clean and delete these temporary state files if they exist:
      • pom.xml.releaseBackup
      • release.properties
  • The local source code repository is one or more commits/revisions behind the remote repository.

Error: Update Center Definition

The release:perform command may log output similar to this:

...
[INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ delta-static-analysis ---
Uploading to maven.jenkins-ci.org: https://repo.jenkins-ci.org/releases/com/andreiprozorov/plugins/delta-static-analysis/1.14/delta-static-analysis-1.14.hpi
Uploading to maven.jenkins-ci.org: https://repo.jenkins-ci.org/releases/com/andreiprozorov/plugins/delta-static-analysis/1.14/delta-static-analysis-1.14.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  23.096 s
[INFO] Finished at: 2021-09-21T18:08:36+10:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy (default-deploy) on project delta-static-analysis: Failed to deploy artifacts: Could not transfer artifact com.andreiprozorov.plugins:delta-static-analysis:hpi:1.14 from/to maven.jenkins-ci.org (https://repo.jenkins-ci.org/releases/): Failed to transfer file https://repo.jenkins-ci.org/releases/com/andreiprozorov/plugins/delta-static-analysis/1.14/delta-static-analysis-1.14.hpi with status code 401 -> [Help 1]

In this case the likely cause is a missing distributionManagement tag in the pom.xml file.

Error: Update Center Authentication

The release:perform command may log output similar to this:

...
[INFO] Executing: /bin/sh -c cd /home/aprozorov/local/src/jenkins/plugins/maven/delta-static-analysis-plugin/target/checkout && /home/aprozorov/.m2/wrapper/dists/apache-maven-3.6.0-bin/2dakv70gp803gtm5ve1ufmvttn/apache-maven-3.6.0/bin/mvn -s /tmp/release-settings8573205907482015672.xml deploy --no-plugin-updates -P consume-incrementals,might-produce-incrementals,jenkins-release, -f pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5.3:perform (default-cli) on project delta-static-analysis: Maven execution failed, exit code: '1' -> [Help 1]

Possible causes of the error:

  • Maven parameters file is missing.
  • Maven parameters file exists but the values of server.username or server.password are missing/incorrect.