I have to run Sonarqube analysis for a Java project which is a subproject among 4 others, something like below:
Parent-project
-> serviceA
-> src/main/java/...
-> serviceB
-> src/main/java/...
-> serviceC
-> src/main/java/...
-> serviceD
-> src/main/java/...
-> gradle.properties
-> sonar.gradle
I know that I can exclude unwanted services as below:
project(":serviceB") {
sonarqube {
skipProject = true
}
}
However the problem is that I do not own the parent project and hence cannot make changes in the global sonar.gradle file as this is being shared other services as well.
Is there a way to have a sonar.gradle only for my project (serviceA), and a gradle task that runs analysis only for my service?
I am completely lost here because the documentation does not seem to tell anything about this.
Any help will be highly appreciated!
I found a solution to this problem. You can actually exclude the unwanted projects under the parent project using following setting in your sonar.gradle:
project(":project-1") {
sonarqube {
skipProject = true
}
}
project(":project-2") {
sonarqube {
skipProject = true
}
}
If you want even more control to a level that you don't want to exclude a whole sub-project but want to include only a part of the sub-project (for example a common shared library where multiple teams contribute and you want to analyze just your team's code), you can do it something like below:
project(":common-project") {
sonarqube {
properties {
property "sonar.inclusions", "src/main/java/**/common/**"
}
}
}
Related
I'm trying to deal with annotation processors. I followed tutorials. Here is my code:
#ExampleAnnotation
private void someMethod(){
System.out.println("hi");
}
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.METHOD)
public #interface ExampleAnnotation {
}
#SupportedAnnotationTypes("org.example.ExampleAnnotation")
public class Processor extends AbstractProcessor {
#Override
public boolean process(Set<? extends TypeElement> anots, RoundEnvironment roundEnvironment) {
anots.forEach(System.out::println);
return true;
}
}
I created META-INF/SERVICES/javax.annotation.processing.Processor
and registered my processor: org.example.Processor. It seems like everything is OK, but block of code in the processor just dont start. I have no idea what is wrong. P.S.: I use Gradle and Java 11.
i fixed my issue and decided to make a little step-by-step tutorial to create simple JAP:
Java-Annotation-Processor-guide
This is guide for annotation processing using gradle
I spent 3 days trying to deal with it, but with this little tutorial you will made JAP in 5 minutes.
sorry for bad english :)
So, first you should do is create gradle subproject for your project:
create project itself with gradle init or intellij
add to your main project's settings.gradle file this line include "*your subproject name, lets say:*annotation-processor"
Congrats, now let go to the processor itself
here is so much tutorials on the web about this part, so you can read something like this https://www.baeldung.com/java-annotation-processing-builde,
or this (Если ты русский): https://habr.com/ru/company/e-legion/blog/206208/
Final step is very easy - you will add your annotation processor to main project.
!!! instead of annotation-processor you should use your subproject name !!!
kotlin (or java + kotlin) -> {
add this plugin to your plugins: id "org.jetbrains.kotlin.kapt" version "1.7.21"
add this to your dependencies:
kapt project('annotation-processor')
compileOnly project('annotation-processor')
}
java -> {
add this to your dependencies:
annotationProcessor project('annotation-processor')
compileOnly project('annotation-processor')
}
(or you can read this on github: https://github.com/Blu3cr0ss/Java-Annotation-Processor-guide)
I'm writing a custom gradle plugin in which I want to have a bunch of common for several of my projects tasks and a sort of a 'main' task to control which of these tasks to turn on.
Regular tasks in the plugin are e.g.:
CopyDockerResourcesTask
CopyContainerFilesTask
PerformAnalysisTask
and the 'main' task is:
BaseProjectTask
so then in the project in build.gradle I'd like to be able to do this:
BaseProjectTask {
copyDockerResources = true
copyContainerFiles = true
performAnalysis = true
}
I want the default behaviour of the plugin to be to not to do anything, only add certain tasks if they are turned on in BaseProjectTask.
I wanted to achieve this with adding task dependency in #TaskAction method of BaseProjectTask:
class BaseProjectTask extends DefaultTask {
private final BaseProjectExtension extension
private final Project project
#Optional
#Input
Boolean copyContainerFiles = false
...
#Inject
BaseProjectTask(Project project, BaseProjectExtension extension) {
this.project = project
this.extension = extension
}
#TaskAction
def execute() {
if (copyContainerFiles) {
project.tasks.assemble.dependsOn(project.tasks.copyContainerFiles)
}
...
}
}
Creating task dependency, this line:
project.tasks.assemble.dependsOn(project.tasks.copyContainerFiles)
doesn't work.
Edit:
My current findings are that defining task dependency in #TaskAction is too late as this is execution phase. I could do it in the constructor (this way it works) but its too early as property copyContainerFiles isn't set yet.
Does anyone know a way of adding code in the task class that would be fired in the configuration phase? I think this is what I'm missing.
You need to configure task dependencies during the build configuration phase, as you surmised.
It's not possible to do it in the #TaskAction method. It's fundamental to the way Gradle works that it needs to know how tasks depend on each other before it starts executing the build. That allows Gradle to do some useful things, such as only executing the tasks that are not up to date, or working out what tasks will execute without actually executing them.
In general, tasks should not be aware of one another1.
When you are trying to do this in a plugin using values in a project extension, you must wait until after the project has evaluated so that the build script code executes first. You can do this with project.afterEvaluate()2.
So you can do the following (using Kotlin DSL3):
project.afterEvaluate {
tasks.register("baseTask") {
if (baseProjectExtension.copyDockerResources)
dependsOn(tasks.getByName("copyDockerResources"))
if (baseProjectExtension.copyContainerFiles)
dependsOn(tasks.getByName("copyContainerFiles"))
if (baseProjectExtension.performAnalysis)
dependsOn(tasks.getByName("performAnalysis"))
}
}
1See How to declare dependencies of a Gradle custom task?
2See https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:project_evaluation
3What I am familiar with. Hopefully not too much trouble to convert to Groovy.
I created a base image for a Java application using Jib which I want to extend using Jib.
(The Java application provides extensibility by loading additional Jars from the classpath)
In the extending gradle project, I did this:
jib {
....
container {
entrypoint = 'INHERIT'
}
...
}
It allowed me to reuse the entrypoint and args attributes added in the base image but I also want to extend/reuse the base classpath file.
As Jib creates /app/jib-classpath-file in the extending gradle project, the base layer /app/jib-classpath-file is not visible ( I would assume).
To workaround the issue, I added this in extending container configuration block.
extraClasspath = ['/app/libs/*']
Is there an idiomatic way of achieving this in Jib? One option I was thinking is to specify unique classpath files in base and extending projects and
use them like this in the Java command line:
java -cp #/app/jib-BASE-classpath-file #/app/jib-EXTENDED-classpath-file, but I am not finding the option of specifying the classpath file.
What is the recommended way? Thanks
Not a total solution but this shows how to remove the jvm args layer from the child image build altogether.
//build.gradle.kts
buildscript {
dependencies {
classpath("com.google.cloud.tools:jib-layer-filter-extension-gradle:0.1.0")
}
}
...
jib {
...
pluginExtensions {
pluginExtension {
implementation = "com.google.cloud.tools.jib.gradle.extension.layerfilter.JibLayerFilterExtension"
configuration (Action<com.google.cloud.tools.jib.gradle.extension.layerfilter.Configuration> {
filters { filter { glob ="**/jib-*-file" } }
})
}
}
}
This filters out files added in any given layer of a given jib build. If all the files from a layer are filtered out as in this case then the layer is never added to the image.
Sadly this does not let you see the contents of the java-classpath-file in the base image, which you would need to be able to extend it.
References:
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#jib-extensions
https://github.com/GoogleContainerTools/jib-extensions/tree/master/first-party/jib-layer-filter-extension-gradle
https://github.com/GoogleContainerTools/jib-extensions
I am trying to write a custom rule for Maven enforcer plugin which is very similar to the RequireSameVersions rule that is included with the enforcer plugin.
I want to look at all dependencies of a project, and if they have a custom property set, then we must ensure that the property is the same across all dependencies (whilst ignoring any dependencies without that property set, as these are version agnostic).
The problem I am facing is that in the code for the RequireSameVersions rule, the artifacts have the version exposed in the API, such that you can call artifact.getVersion() for each dependent artifact, however the only Object that it seems you can call getProperties() on is the maven project itself.
Thus, the code I would really like to write for the custom rule is:
public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
Set<String> versions = new HashSet<String>();
MavenProject project = null;
try {
project = (MavenProject) helper.evaluate("${project}");
Set<Artifact> dependentArtifacts = project.getDependencyArtifacts();
for (Artifact artifact : dependentArtifacts) {
Properties childProperties = getProperties(artifact); //TODO: what to put in this method
String versionNumber = childProperties.getProperty("bespoke.version");
if (versionNumber != null) {
versions.add(versionNumber);
}
}
} catch (ExpressionEvaluationException eee) {
throw new EnforcerRuleException(
"Unable to retrieve the MavenProject: ", eee);
}
if (versions.size() > 1) {
// we have more than one version type across child projects, so we
// fail the build.
throw new EnforcerRuleException(
"modules of this project refer to more than one version");
}
}
However, I don't know what to put in the getProperties(artifact) method. Any suggestions here would be fantastic, thank you.
I'm reading up on Gradle and am very interested in it, specifically because (it appears) that it allows the introduction of inheritance into the build process. For instance, if I have a Java web app that might be packaged and deployed to Google App Engine instances as well as Amazon EC2 instances, I need a sophisticated build that can take the same Java, XML, PROPERTIES, CSS and image files and package/deploy them into 2 drastically-differently packaged WAR files.
GAE apps are very specific as to how they are packaged; EC2 (pretty much) just require that you conform to servlet specs. GAE apps get "deployed" by running an update command from the appcfg.sh script that comes with your SDK; EC2 has their own way to deploy apps. The point is, they are very different packaging/deployment processes for both PaaS providers:
public abstract class PackageTask {
// ...
}
// Package my Eclipse project for deployment to GAE.
public class AppEnginePackageTask extends PackageTask {
// ...
}
// Package my Eclipse project for deployment to EC2 instances.
public class AmazonPackageTask extends PackageTask {
// ...
}
public abstract class DeployTask {
// ...
}
// Deployment to GAE.
public class AppEngineDeployTask extends DeployTask {
// ...
}
// Deployment to EC2.
public class AmazonDeployTask extends DeployTask {
// ...
}
Then, I might have a myapp.gradle buildfile that templates the build order of tasks:
clean()
compile()
package()
deploy()
...and somehow, I can configure/inject AppEnginePackageTask/AppEngineDeployTask in place of package()/deploy() for a GAE-based build, or I can configure/inject AmazonPackageTask/AmazoneDeployTask into those templated tasks. Again, I'm not sure how to do this (or even if Gradle can do this), but it's what I'm after.
My understanding was that Gradle can do this. Ant can also be forced to have highly-modular, elegant builds that work this way, but being XML-based, it takes some finessing, whereas an OOP-based language like Groovy makes this cleaner and simpler.
However, all the examples I see of Gradle tasks take the following form:
task package(dependsOn: 'compile') {
// ...
}
task deploy(dependsOn: 'package') {
// ...
}
So I ask: these look/feel like non-OOP task definitions. Is my understanding of Gradle (and its OOP nature) fundamentally incorrect? What am I missing here? How can I accomplish these notions of "configurable/injectable build templates" and inheritance-based tasks? Thanks in advance!
Edit I re-tagged this question with "groovy" because Gradle buildscripts are written in a Groovy DSL, and someone who happens to be a Groovy-guru (say that 5 times fast) might also be able to chime in even if they know little about Gradle.
As described here, there are simple tasks and enhanced tasks. The latter are much more flexible and powerful.
The following example isn't exactly what you describe, re:injection, but it illustrates OOP.
Here is the sample build.gradle file. It avoids "package" as that is a keyword in Java/Groovy. The 'build' target depends on 'compile' and some flavour of 'doPack', depending on a property called 'pkgTarget'.
task compile << {
println "compiling..."
}
task build() << {
}
build.dependsOn {
compile
}
build.dependsOn {
if (pkgTarget == "Amazon") {
task doPack(type: AmazonPackageTask)
} else if (pkgTarget == "Google") {
task doPack(type: GooglePackageTask)
} else {
task doPack(type: MyPackageTask)
}
}
where the tasks are defined later in the same file. (Per doc, this code can go into a "build src" directory):
// -----
class MyPackageTask extends DefaultTask {
def init() { println 'common stuff' }
#TaskAction
def doPackage() {
println 'hello from MyPackageTask'
}
}
class AmazonPackageTask extends MyPackageTask {
#TaskAction
def doPackage() {
init()
println 'hello from AmazonPackageTask'
}
}
class GooglePackageTask extends MyPackageTask {
#TaskAction
def doPackage() {
init()
println 'hello from GooglePackageTask'
}
}
and here is the gradle.properties file:
pkgTarget=Amazon