Override sonar projectKey when using maven - maven

I want to group 25 modules under a single project key so I can get a consolidated view of code duplication. However the sonar maven plugin uses the <groupId>:<artifactId> so each project is separate.
I've tried overriding the sonar.projectKey but the maven plugin doesn't consider it.
Is there a way of grouping modules together under a single name so that you can have an aggregate view?
Or is there some other in the sonarqube server to get that aggregate view?

As far as I can tell, and contrary to some other forum posts, with at least v3.2 of the maven-sonar-plugin (maybe earlier) the sonar.projectKey property is respected and overrides the default of ${project.groupId}:${project.artifactId}.
Checking the source code also confirms it first looks for the property before defaulting it.
org.sonarsource.scanner.maven.bootstrap.MavenSonarRunner.java
private static void defineProjectKey(MavenProject pom, Properties props) {
String key;
if (pom.getModel().getProperties().containsKey(ScanProperties.PROJECT_KEY)) {
key = pom.getModel().getProperties().getProperty(ScanProperties.PROJECT_KEY);
} else {
key = getSonarKey(pom);
}
props.setProperty(MODULE_KEY, key);
}
private static String getSonarKey(MavenProject pom) {
return new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString();
}
org.sonarsource.scanner.api.ScanProperties
String PROJECT_KEY = "sonar.projectKey";
So by setting the following in the POM, for example, the projectKey can be overriden:
<properties>
<sonar.projectKey>myprefix:${project.groupId}:${project.artifactId}</sonar.projectKey>
</properties>
Tested on Maven 3.3.9. In case this helps anyone!
Link to original GitHub Source:
https://github.com/SonarSource/sonar-scanner-maven/blob/master/src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java

I have a similar setup and use a multi modules / aggregator project for that http://maven.apache.org/pom.html#Aggregation.
Just pass the aggregator pom that contains the modules to the sonar build and it should group all modules together. The grouping name is taken from the aggregator artifact-property (and can be overwritten by its name-property).
<groupId>...</groupId>
<artifactId>aggregator-project</artifactId>
<version>...</version>
<packaging>pom</packaging>
<name>Group name overrites artifactId</name>
<modules>
<module>my-project</module>
<module>another-project</module>
</modules>

Related

Extending property from parent pom in child pom with maven

I am working in a large project where we have multiple modules, each as their own maven project with a common parent pom.
Among other things, the parent pom defines the Sonar integration on our build server. Our Sonar plugin on the build server evaluates the property "sonar.exclusions" in order to skip files which we do not want to be analysed.
For that purpose, we define a property in the parent pom:
<properties>
<sonar.exclusion>**/generated/**/*,**/migration/**/*</sonar.exclusions>
</properties>
Now, in one of our projects, we want to add to this exclusion list. I do not want to replace those exclusions defined in the parent but I also do not want to repeat them. What I am looking for is something along these lines:
<properties>
<sonar.exclusions>${sonar.exclusions},**/shadow/compare/**/*</sonar.exclusions>
</properties>
In the end, I want the content of ${sonar.exclusions} to be
**/generated/**/*,**/migration/**/*,**/shadow/compare/**/*
However, trying the above results in an error:
pom.xml has 1 error [main] ERROR org.apache.maven.cli.MavenCli - Resolving expression: ${sonar.exclusions}': Detected the following recursive expression cycle in 'sonar.exclusions': [sonar.exclusions]
Is there a way to achieve what I want?
You can define a property <sonar.standard.exclusions> in your parent POM that contains your standard exclusions and set <sonar.exclusions>${sonar.standard.exclusions}</sonar.exclusions>
Then you can overwrite the property in your POM as
<sonar.exclusions>${sonar.standard.exclusions},**/shadow/compare/**/*</sonar.exclusions>

Jenkinsfile and POM version

After we fetch POM model like described in Krzysztof KrasoĊ„'s answer in extract pom version in a jenkins pipeline. Call to pom.version returns the fully qualified name of the artifact and not just the version.
For example
#NonCPS
def version() {
pom = readMavenPom file: 'pom.xml'
pom.version
}
for
<groupId>com.test.app</groupId>
<artifactId>app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
will produce
com.test.app:app:pom:1.0.0-SNAPSHOT
Is there a way to return just the version part from returned Model without doing any String manipulation?
You should not call regular (CPS-transformed) methods, or Pipeline steps inside #NonCPS methods because they requires CPS-transformation.
See more in README.md.

Maven how set absolute path for parent pom

with maven 3 i have a parent project at 'C:/travail/parent'.
I have several child-projects who, for various reasons, can change locations.
To make a war, the relativePath tag must be set.
<parent>
<groupId>framework.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>C:/Travail/parent/pom.xml</relativePath>
</parent>
Question: How can I put an absolute path for the parent? The following doesn't work.
<relativePath>/C:/Travail/parent/pom.xml</relativePath>
You cannot use an absolute path for your parent pom, the name itself of the configuration entry is quite self explanatory (relative path).
From the official Maven model documentation for this element:
The relative path of the parent pom.xml file within the check out. If not specified, it defaults to ../pom.xml. Maven looks for the parent POM first in this location on the filesystem, then the local repository, and lastly in the remote repo. relativePath allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent POM. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. This feature is only for enhancing the development in a local checkout of that project. Set the value to an empty string in case you want to disable the feature and always resolve the parent POM from the repositories.
Default value is: ../pom.xml.
You can't even use a shortcut or symbolic link for the same, distributed together with each and every module and pointing at the absolute file location, it would not work (and you shouldn't use such a trick anyway, even if it was going to work).
You can't even use a property as value placeholder of the relativePath element. Something like:
<parent>
<groupId>framework.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>${path.to.parent}</relativePath>
</parent>
And try to inject it at build time like:
mvn clean install -Dpath.to.parent=C:/somewhere/pom.xml
Would simply not work, as also documented by the following Maven tickets:
MNG-2569: Expressions not evaluated inside
MNG-624: automatic parent versioning
The only reasonable use case for this configuration entry is, as mentioned in the official documentation, for flat-structured multi-module projects, where modules and parent project are located at the same directory level.
Otherwise, and more suitable for your use case, you should provide the parent pom as part of the shared Maven repository (if any) or require a maven install (so that it will be available in the local maven cache) of the parent project upfront for any new version before any required maven action on the children/module projects.

Inherit build plugin/extension/... in Maven

Say a Maven project has a cool build plugin configured:
<project>
...
<build>
... extensions etc.
</build>
...
</project>
I want this configuration to be reusable, so that I can run the goals provided by the plugins/extensions in any new project. The above project might exist just so that other projects can reuse the config.
What is the best way to achieve this?
Use a parent.pom. Deploy this pom to your local repository. Of course you could configure parent.poms for each type of project that you regularly develop in your organisation. Probably a master.pom with general values (location of servers, organisation name, general code style...) is a good idea. The project specific poms would use this as parent.
Declare this pom.xml as of type pom:
<type>pom</type>
and declare it as a parent in every "child" pom.xml that needs the configured plugins: http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance

Maven Project Properties

In my Maven pom.xml, I have seen following thing;
project.build.sourceDirectory
project.build.scriptSourceDirectory
project.build.testSourceDirectory
project.build.outputDirectory
project.build.testOutputDirectory
project.build.directory
Where exactly are these defined? How do I know what location they represent locally ?
As Stewart says, these are defined in the Super POM (Introduction to the POM - Super POM).
To see the values they have for a project, run mvn help:effective-pom to show your project's POM merged with the definitions from the Super POM:
...
<build>
<sourceDirectory>XXX/src/main/java</sourceDirectory>
<scriptSourceDirectory>XXX/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>XXX/src/test/java</testSourceDirectory>
<outputDirectory>XXX/target/classes</outputDirectory>
...
You can override these values in your own projects; using the properties to refer to them means that plugins referring to these paths will pick up the overridden values.

Resources