Use ktlint to format during maven build - maven

I used the following settings for ktlint which allowed auto-formatting for all files during a local maven build but never triggered a pipeline failure if formatting was incorrect:
<plugin>
<groupId>com.github.gantsign.maven</groupId>
<artifactId>ktlint-maven-plugin</artifactId>
<version>1.6.1</version>
<executions>
<execution>
<id>format-and-check</id>
<goals>
<goal>format</goal>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
For ktlint to trigger a pipeline failure if formatting is incorrect I changed the settings to
<execution>
<id>verify-code-style</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
Which does trigger a failure instantly.
But - now I cannot do a local maven build and make use of auto-formatting. Instead it instantly triggers a failure, requiring manual action for example Needless blank line(s) in class X on line Y.
I would like to have the best of both worlds - trigger a failure in the pipeline and make use of auto-formatting locally. Is there any way to achieve this?

Since you want differing behaviour locally compared to your CI, I think the simplest solution would to just run the format goal before the build command that you run locally.
So instead of mvn deploy (or package or whatever you run), just run
mvn ktlint:format deploy

Related

PMD maven plugin: How to specify a different ruleset for tests?

I need to configure the PMD maven plugin to scan test source code with less strict checks comparing to production code.
Is there a way to do it?
You'll probably need to configure two separate executions for the plugin. This allows you to use different configurations. Once execution checks only production code (<includeTests>false</includeTests>) and the other checks test-code only (<includeTests>true</includeTests> and <excludeRoots><excludeRoot>${basedir}/src/main/java</excludeRoot></excludeRoots>).
If you share your solution, we can add it as an example on https://maven.apache.org/plugins/maven-pmd-plugin/
Another way to do it is to use the same code quality rules for all your code, avoiding to make compromises because it's "just test code". While test code doesn't run in production, it's used to test production code, so you might consider the test code then as your weakest link if you use less strict checks...
Here's the complete plugin configuration for this scenario:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<configuration>
<includeTests>false</includeTests>
<rulesets>
<ruleset>config/pmd/pmdMain.xml</ruleset>
</rulesets>
<linkXRef>false</linkXRef>
</configuration>
<executions>
<execution>
<id>pmd-main</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<id>pmd-test</id>
<phase>verify</phase>
<goals>
<goal>pmd</goal>
<goal>check</goal>
</goals>
<configuration>
<targetDirectory>${project.build.directory}/pmdTest/</targetDirectory>
<includeTests>true</includeTests>
<excludeRoots>
<excludeRoot>${basedir}/src/main/java</excludeRoot>
</excludeRoots>
<rulesets>
<ruleset>config/pmd/pmdTest.xml</ruleset>
</rulesets>
</configuration>
</execution>
<execution>
<id>cpd</id>
<phase>verify</phase>
<goals>
<goal>cpd-check</goal>
</goals>
</execution>
</executions>
</plugin>
It uses the ruleset config/pmd/pmdMain.xml for the main code without tests. This is configured directly at the plugin level.
The ruleset config/pmd/pmdTest.xml is used for the test code only. This is configured in the execution with id pmd-test.
It has one downside though: PMD is run three times.... twice for the main code, and once for the test code. The reason is that "pmd:check" triggers automatically "pmd:pmd", but it uses only the standard configuration (e.g. ignored the lifecycle/execution id).
The execution "pmd-test" calls once "pmd:pmd" for the test code (which creates target/pmdTest/pmd.xml), then calls pmd:check - which itself calls pmd:pmd and uses the default configuration - and then runs pmd:check actually, which uses the execution configuration and uses target/pmdTest/pmd.xml to decide whether to fail the build.

Can Sonar Scan be triggered as part of regular maven Build command like " mvn build"?

Im looking to see any maven configuration which will enable me to run Sonar Scan on my code for every maven build. I dont want to use a separate goal but somehow enforce it as part of users regular build commands.
You can attach Sonar to a phase (e.g. verify) like this:
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.5.0.1254</version>
<executions>
<execution>
<id>verify-sonar</id>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
This also works with other phases like compile or package.

How to invoke specific execution

I am trying to replace maven exec with MavenInvokerPlugin because of problems on Jenkins with forwarding the maven settings file.
So in bash it looks straight:
mvn dependency:copy-dependencies#resolve-maven-deps
My translation to MavenInvokerPlugin configuration is
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<projectsDirectory>${project.basedir}/src/main/docker</projectsDirectory>
<localRepositoryPath>${project.build.mavenDependencies}</localRepositoryPath>
<goal>dependency:copy-dependencies#resolve-maven-deps</goal>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>run</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
It looks like that execution id is completely ignored, because I tried random strings and mvn builds the project with success.
mvn dependency:copy-dependencies#asdfasdfa
So I'd like to know whether this feature is supported at all and what I am doing wrong.
P.S. I know that calling maven out of maven is anti pattern, but here is exactly that rare case when there is no other way.
After looking at projects using maven invoker I figured out the trick.
goal tag is not used, instead provide invokerPropertiesFile:
<pom>${project.basedir}/xxx/pom.xml</pom>
<invokerPropertiesFile>${project.basedir}/invoker.properties</invokerPropertiesFile>
content of the file:
invoker.goals=compile -P resolve-maven-deps

${session.executionRootDirectory} is not recognized by sonar-maven-plugin

I have several levels of nested Maven projects, where every module can participate in the global integration tests. To have a global, multi module coverage, I've configured jacoco to use and share the same file accross modules, using the Maven variable ${session.executionRootDirectory}:
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<propertyName>jacoco.failsafeArgLine</propertyName>
<destFile>${session.executionRootDirectory}/target/jacoco-it.exec</destFile>
</configuration>
</execution>
This way, the same data file is used by each module, no matter how deep it is nested in the submodules. I've checked, a correct data file is generated by jacoco when launching "mvn clean install".
Now the problem appears when launching mvn sonar:sonar. It seems that the plugin can not replace that variable with the real path. I can see the following in the logs
[INFO] JaCoCoItSensor: JaCoCo IT report not found: /home/tomcat/.jenkins/jobs/MYJOB/workspace/${session.executionRootDirectory}/target/jacoco-it.exec
It doesn't work better when using #{session.executionRootDirectory}.
Any workaround?
Following a comment in this bug report at SonarSource, advising to use the following configuration:
<plugin>
<groupId>com.github.goldin</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>0.2.5</version>
<executions>
<execution>
<id>set-sonar.jacoco.reportPath</id>
<goals>
<goal>set-properties</goal>
</goals>
<phase>initialize</phase>
<configuration>
<rawProperties>
sonar.jacoco.itReportPath = ${session.executionRootDirectory}/target/jacoco-it.exec
</rawProperties>
<addDollar>true</addDollar>
</configuration>
</execution>
</executions>
</plugin>
... which was unfortunately not compatible with Maven 3.1+, I've used and built from sources that fork, and then I was able to make everything work correctly with Maven 3.2.3.

Maven: Running an arbitrary command build phase

How do I run a simple command (or a shell script containing said command) during the maven build phase?
My specific case is I'd like to run the protocol buffer compiler (protoc) that generates a java class prior to the java compiler running.
I feel like it should possibly be part of the "process resources" phase of the build goal (see http://books.sonatype.com/mvnref-book/reference/lifecycle-sect-common-goals.html) but they only discuss copying files that happen to be shell scripts, not running a script.
One solution to your problem is to use the maven-antrun-plugin. That is what I use to build some scriptlike commands within a maven build:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<echo message="basedir=${basedir}" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
With this a simple echo task is started in the build phase generate-sources. So you could extent this solution to your needs.
I like this ant aproach more than e.g. the exec-maven-plugin because it is imho in a way more system independent. But thats a thing of preference.

Resources