You can put band-aids... for example we use internally a parent pom that decouples from core, something very close to
<?xml version="1.0" encoding="UTF-8"?>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cloudbees</groupId>
<artifactId>cloudbees-internal-parent</artifactId>
<version>8</version>
</parent>
<groupId>com.cloudbees.jenkins.plugins</groupId>
<artifactId>jenkins-plugins</artifactId>
<version>23-SNAPSHOT</version>
<packaging>pom</packaging>
<name>CloudBees Jenkins Plugin Parent</name>
<description>The CloudBees Jenkins Plugins Parent Project</description>
<inceptionYear>2011</inceptionYear>
<scm>
<connection>...</connection>
<developerConnection>...</developerConnection>
<tag>HEAD</tag>
</scm>
<properties>
<jenkins.version>1.532.2</jenkins.version> <!-- TODO 1.532.3 once we produce 1.532.3.1 -->
<hpi-plugin.version>1.108</hpi-plugin.version>
<stapler-plugin.version>1.17</stapler-plugin.version>
<concurrency>1</concurrency> <!-- may use e.g. 2C for 2 × (number of cores); TODO until 1.545 >1 is unreliable during clean builds -->
</properties>
<prerequisites>
<maven>3.0.2</maven>
</prerequisites>
<dependencyManagement>
<dependencies>
<!-- static analysis -->
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.github.stephenc.findbugs</groupId>
<artifactId>findbugs-annotations</artifactId>
<version>1.3.9-1</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-core</artifactId>
<version>${jenkins.version}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-war</artifactId>
<version>${jenkins.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>${jenkins.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- static analysis -->
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.stephenc.findbugs</groupId>
<artifactId>findbugs-annotations</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- dependencies provided by virtue of running in Jenkins -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- dependencies needed for testing -->
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-war</artifactId>
<type>war</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--
Since new versions need to overwrite old versions, it's better
not to have version number in the .hpi file name.
-->
<finalName>${project.artifactId}</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<!--
Because Eclipse lacks JSR-269 support, put the output
to a different directory
-->
<configuration>
<buildOutputDirectory>target/eclipse-classes</buildOutputDirectory>
<additionalProjectnatures>
<!-- enable Groovy nature by default for DSLD support -->
<projectnature>org.eclipse.jdt.groovy.core.groovyNature</projectnature>
</additionalProjectnatures>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.17</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.5</version> <!-- TODO do we want 1.5-jenkins-1? -->
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.0-alpha-5</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.0.201403182114</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
<plugin>
<groupId>org.kohsuke.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0-rc-5-patch-2</version>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<version>${stapler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>${hpi-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.11</version>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<version>1.19</version>
</plugin>
<plugin>
<groupId>org.jvnet.maven-antrun-extended-plugin</groupId>
<artifactId>maven-antrun-extended-plugin</artifactId>
<version>1.43</version>
</plugin>
<plugin>
<groupId>org.jvnet.sorcerer</groupId>
<artifactId>maven-sorcerer-plugin</artifactId>
<version>0.8</version>
</plugin>
<plugin>
<groupId>org.kohsuke</groupId>
<artifactId>access-modifier-checker</artifactId>
<version>1.4</version>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
</plugin>
<plugin>
<groupId>com.cloudbees</groupId>
<artifactId>maven-license-plugin</artifactId>
<version>1.7</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>display-info</id>
<phase>validate</phase>
<goals>
<goal>display-info</goal>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<enforceBytecodeVersion>
<maxJdkVersion>1.${java.level}</maxJdkVersion>
<excludes>
<!-- Makes no sense to check core itself: -->
<exclude>org.jenkins-ci.main:jenkins-core</exclude>
<exclude>org.jenkins-ci.main:cli</exclude>
<exclude>org.jenkins-ci.main:jenkins-test-harness</exclude>
</excludes>
<!-- To add exclusions in a Jenkins plugin, use:
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>display-info</id>
<configuration>
<rules>
<enforceBytecodeVersion>
<excludes combine.children="append">
<exclude>…</exclude>
</excludes>
</enforceBytecodeVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
(or just override java.level) -->
</enforceBytecodeVersion>
</rules>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.0-beta-2</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.${java.level}</source>
<target>1.${java.level}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<id>check</id>
</execution>
</executions>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java1${java.level}</artifactId>
<version>1.0</version>
</signature>
</configuration>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<contextPath>/jenkins</contextPath>
<!-- TODO specify ${java.level} when JENKINS-20679 implemented -->
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<extensions>true</extensions>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<goals>deploy</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.kohsuke</groupId>
<artifactId>access-modifier-checker</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>test-in-groovy</id>
<goals>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.6.5</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>hudson.udp</name>
<value>33849</value>
</property>
</systemProperties>
<reuseForks>true</reuseForks>
<forkCount>${concurrency}</forkCount>
</configuration>
</plugin>
<plugin>
<groupId>com.cloudbees</groupId>
<artifactId>maven-license-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<!--requireCompleteLicenseInfo>true</requireCompleteLicenseInfo-->
<generateLicenseXml>target/${project.artifactId}/WEB-INF/licenses.xml</generateLicenseXml>
<inlineScript><![CDATA[
filter {
def plugins = [] as Set
// collect all Jenkins plugins
models.entrySet().each { e ->
if (e.value.packaging=="hpi")
}
// filter out dependencies that don't belong to this plugin
models.entrySet().removeAll(models.entrySet().findAll { e ->
def a = e.key;
if (a.dependencyTrail.size()>0 && plugins.contains(a.dependencyTrail[1]))
return true; // ignore transitive dependencies through other plugins
// if the dependency goes through jenkins core, we don't need to bundle it in the war
// because jenkins-core comes in the <provided> scope, I think this is a bug in Maven that it puts such
// dependencies into the artifact list.
if (a.dependencyTrail.find { trail -> trail.contains(":hudson-core:") || trail.contains(":jenkins-core:") })
return true;
return false;
})
}
]]></inlineScript>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/Messages.class</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>all-tests</id>
<activation>
<property>
<name>!test</name>
</property>
</activation>
<properties>
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
</properties>
</profile>
</profiles>
</project>
That whole business of over-specifying plugin versions of *every plugin in the world* is a whole waste of time. Especially the over-reliance on properties to control the versions. There are only two reasons to use properties for versions:
1. You want to keep the same version in sync
2. You need to be able to override the version from the command line.
So in our case with the above pom, if you want to check your plugin against a different version of jenkins
Because of vagrancies of the hpi and stapler plugins, sometimes when you are testing with a newer version of Jenkins you also need to use a newer version of the hpi or stapler plugins, hence those have versions controlled by properties.
The only other plugins we configure are ones that we want as part of our standard build process.
Keep in mind that reving the parent pom is a *big deal*... the current parent makes that double big deal... at least internally reving the parent is ok other than we need to do a bit of work pushing the rev to all our plugin source repos so that we don't forget to update it again before the next plugin release
Now is the CloudBees style-parent something that the Jenkins community should adopt? Well there was an action item on myself and Jesse Glick to see about pushing something based on our parent into OSS as an alternative... perhaps... though my personal preference is not to force two parent switching churns on plugin developers.
As such I would rather fix the hpi plugin so that people can have a "Maven plugin done right" experience out of the box and see that the Maven pains of Jenkins plugin development are actually a result of not having the Maven build done right in the first place and not an intrinsic problem of Maven (other than our docs are non-existent and thus people don't learn the right way of writing maven plugins)