Does the gradle file system watcher work for subprojects? - gradle

I recently splitted our micornaut project in seperate module, but since then the continous build doe s not work anymore for the subprojects. But changes in the root project will still be detected.
The build.grade of the root project looks like this:
plugins {
id 'java'
id "com.github.johnrengelman.shadow" version "7.0.0"
id "io.micronaut.application" version "3.6.5"
}
version = "0.1"
group = "com.example"
repositories {
mavenCentral()
}
configurations {
compile
}
micronaut {
runtime("netty")
testRuntime("junit5")
processing {
incremental(true)
annotations("*")
}
}
dependencies {
implementation project(':child1')
implementation project(':child2')
}
And a child build.gradle like this:
plugins {
id 'java'
id 'io.micronaut.library'
}
group 'com.example'
version '0.1'
repositories {
mavenCentral()
}
dependencies {
implementation project(":child1")
}
The gradle.properties like this:
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.caching=true
org.gradle.vfs.verbose=true
org.gradle.vfs.watch=true
micronautVersion=3.7.4
version=7.4.0
I start the application with *gradle run -t. In settings.gradle are all subprojects included. Any ideas how to fix this?
EDIT: Output of gradle run --dry-run :
VFS> Statistics since last build:
VFS> > Stat: Executed stat() x 0. getUnixMode() x 0
VFS> > FileHasher: Hashed 0 files (0 bytes)
VFS> > DirectorySnapshotter: Snapshot 0 directory hierarchies (visited 0 directories, 0 files and 0 failed files)
Received 4102 file system events since last build while watching 1 locations
Virtual file system retained information about 545 files, 113 directories and 0 missing files since last build
:child1:compileJava SKIPPED
:child2:compileJava SKIPPED
:child3:compileJava SKIPPED
:compileJava SKIPPED
:processResources SKIPPED
:classes SKIPPED
:child1:processResources SKIPPED
:child1:classes SKIPPED
:child1:jar SKIPPED
:child2:processResources SKIPPED
:child2:classes SKIPPED
:child2:jar SKIPPED
:child3:processResources SKIPPED
:child3:classes SKIPPED
:child3:jar SKIPPED
:run SKIPPED
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.4.2/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 2s
Received 16 file system events during the current build while watching 1 locations
Virtual file system retains information about 564 files, 117 directories and 0 missing files until next build
VFS> Statistics during current build:
VFS> > Stat: Executed stat() x 4. getUnixMode() x 0
VFS> > FileHasher: Hashed 15 files (40.351 bytes)
VFS> > DirectorySnapshotter: Snapshot 4 directory hierarchies (visited 4 directories, 19 files and 0 failed files)

Related

How to exlude tests from included dependecies

We have a gradle file where the upper webservices is dependent of the lower project core.
In the build.gradle of webservices the dependecy is included:
dependencies {
implementation project(':core')
}
But now things are going strange. When I run a test inside IntelliJ the whole test of core will start until finally the single test case of webservices will start.
Even on the command line I run into the same problem:
/opt/gradle/gradle-7.5.1/bin/gradle webservices:test --tests com.example.MyTests.test
end in the funny behaviour that the complete core test are running:
> Configure project :core
> Task :core:test
In the test section of webservices is nothing else as:
test {
useJUnitPlatform()
}
Trying to exclude the tests of core by adding something like
exclude '**/core/**'
are not ending in the behaviour I would expect.
It there a way to tell gradle not include the tests of the project which is inside the depedency?
EDIT: Add some information after User51 comment:
/opt/gradle/gradle-7.5.1/bin/gradle web:test --dry-run
> Configure project :core
BUILD NUMBER: -1
BUILD DATE: 2023-02-02_08-58-47
clean synchronize dir
spi.Extension touched!...
:abc:compileJava SKIPPED
[...]
:abc:test SKIPPED
:abc:jar SKIPPED
:core:compileJava SKIPPED
[...]
:core:test SKIPPED
:core:updateTestTimestamps SKIPPED
:core:jar SKIPPED
:webservices:wsdl2javaTask SKIPPED
:webservices:compileJava SKIPPED
[...]
:webservices:test SKIPPED
Futher in the build.gradle of core is written this:
if (project.hasProperty("RUN_TESTS_FOR_JAR") && RUN_TESTS_FOR_JAR.equals("false")) {
println "Tests are skipped!..."
jar.dependsOn(updateTestTimestamps)
} else {
jar.dependsOn(test, updateTestTimestamps)
}
build.dependsOn(updateTestTimestamps)
Thanks,
Markus

elasticsearch use a custom 3rd party artifact

How can I use a custom 3rd party artifact in ElasticSearch locally ?
From docs
Update the dependency declaration of the artifact in question to match
the custom build version. For a file named e.g. jmxri-1.2.1.jar the
dependency definition would be :jmxri:1.2.1 as it comes with no group
information:
But I get an exception because getGroup returns null
Steps to reproduce
clone elasticseach into /tmp
create a directory /tmp/elasticsearch/localRepo
add to (root) build.gradle allprojects here the following
allprojects {
repositories {
flatDir {
dirs 'localRepo'
}
}
}
my local jar is /tmp/elasticsearc/localRepo/test-3.2.1.jar
add here
api ':test:3.2.1'
run ./gradlew localDistro
Error message
FAILURE: Build completed with 2 failures.
1: Task failed with an exception.
-----------
* Where:
Build file '/tmp/elasticsearch/client/sniffer/build.gradle' line: 41
* What went wrong:
A problem occurred evaluating project ':client:sniffer'.
> Cannot invoke "String.startsWith(String)" because the return value of "org.gradle.api.artifacts.Dependency.getGroup()" is null
2: Task failed with an exception.
-----------
* What went wrong:
A problem occurred configuring project ':client:sniffer'.
> Cannot invoke "java.lang.Comparable.compareTo(Object)" because the return value of "java.util.function.Function.apply(Object)" is null
BUILD FAILED in 925ms
19 actionable tasks: 19 up-to-date
Dependencies always need a group set like
"group:module:version"
You also need that for flatDir repositories but the group doesn't matter and can be anything as far as I know. I used "test" in the example below
repositories {
flatDir {
dirs(" /tmp/elasticsearch/localRepo")
}
}
dependencies {
api 'test:test:3.2.1'
}

Gradle - Run pitest only on subprojects

I'm trying to have Jenkins run pitest on my project.
The fact that there is a parent build.gradle with sub-projects seems to be an issue.
When running gradle pitest I get:
12:14:17 PIT >> INFO : Sending 0 test classes to minion
12:14:17 PIT >> INFO : Sent tests to minion
12:14:17 PIT >> SEVERE : Error generating coverage. Please check that your classpath contains JUnit 4.6 or above.
Exception in thread "main" org.pitest.util.PitError: Coverage generation minion exited abnormally. Please check the classpath.
I tried configuring pitest only for the subprojects, as suggented in some posts, but doesn't make any difference
subprojects { subproject ->
pitest {
verbose = true
targetClasses = ['com.xyz.*']
threads = 16
enableDefaultIncrementalAnalysis = true
historyInputLocation = ['build/reports/pitest/fastermutationtesting']
historyOutputLocation = ['build/reports/pitest/fastermutationtestingoutput']
outputFormats = ['XML', 'HTML']
timestampedReports = true
mutationThreshold = 80
}
If I try to run pitest on the subprojects, e.g. gradle subOne:pitest gradle says that such task does not exist.
Any suggestion?
The issue was actually the way the plugin was applied.
After setting
id 'info.solidsoft.pitest' version '1.3.0' apply false
in plugins and then adding
apply plugin: 'info.solidsoft.pitest'
in subprojects it all works fine.
try gradle :subOne:pitest.
You can include pitest in the main project and not needed to repeat for subprojects

Conditionally skip subproject in multi-module Gradle build

Consider the following Gradle project structure:
- root
|- build.gradle
|- barProject
|- build.gradle
|- fooProject
|- build.gradle
where the root build.gradle configures its subprojects like so:
subprojects {
apply plugin: 'java'
//bunch of other stuff
}
Now when I call gradlew build on the root project it automatically configures both subprojects and then builds them - all well and good.
I also know that I can skip a specific task with various means (onlyIf(), [taskName].enabled = false, etc.) but when I utilize any of those on build Gradle still runs all the dependent tasks (compileJava, processResources, classes, etc.) until finally hitting build which it then skips.
My question is, is there any way to have Gradle stop and go to the next subproject right after the configuration phase?
EDIT:
To clarify; each subproject has a property called skip that is evaluated in the configuration phase.
Now when I call gradlew build on the root project I want Gradle to, ideally, check that property and if it's true then to completely skip the corresponding project.
Executing external task 'build'...
//check project.skip -> IF true -> skip project, go to :foo ELSE continue
:bar:compileJava
:bar:processResources UP-TO-DATE
:bar:classes
:bar:jar
:bar:startScripts
:bar:distTar
:bar:distZip
:bar:assemble
:bar:compileTestJava UP-TO-DATE
:bar:processTestResources UP-TO-DATE
:bar:testClasses UP-TO-DATE
:bar:test UP-TO-DATE
:bar:check UP-TO-DATE
:bar:build
//check project.skip -> IF true -> skip project, go to end ELSE continue
:foo:compileJava
:foo:processResources UP-TO-DATE
:foo:classes
:foo:jar
:foo:startScripts
:foo:distTar
:foo:distZip
:foo:assemble
:foo:compileTestJava UP-TO-DATE
:foo:processTestResources UP-TO-DATE
:foo:testClasses UP-TO-DATE
:foo:test UP-TO-DATE
:foo:check UP-TO-DATE
:foo:build
BUILD SUCCESSFUL
I hope this makes more sense
Well, first of all: An easy solution would be calling exactly the task(s) you need. In simple Gradle builds, task names are unique. However, in multi-project builds, each project can have a task with a specific name. This is the reason why Gradle introduced task paths. Task paths combine the unique project paths with the intra-project unique task names: :projectX:taskY.
Using project paths, you can easily specify the project-specific task you want to execute: :build for the build task in the root project and :<subproject>:build for the build task in a subproject. If a task name, e.g. build, is provided for a multi-project build, Gradle will search through any project (root and subs) for a task with the specified name and execute them all. This explains the current behaviour.
The task names for execution are managed by a StartParameter object of the Gradle Settings. These Settings can be modified in your settings.gradle file, where you also include subprojects:
include ':foo', ':bar'
startParameter.excludedTaskNames += ':foo:build'
This line excludes the build task of the foo subproject from the execution. You could add the subproject task path (even independent from the task name) to the excluded task names, if a specific condition is met. But, I did not find a way to access the Settings in your build file, so this solution can not be used during configuration phase. However, if your condition is solely based on project / system properties, they can be accessed from settings.gradle.
Another solution for the configuration phase came to my mind, but it's basically what you already mentioned, because it simply skips the tasks:
if (project.skip) {
project.tasks.all { task -> task.enabled = false }
}
This way, all tasks from the project (not only the build task) will be skipped.
Please consider, that tasks can also be executed, because they create a dependency for another project. Even gradle :bar:build will execute the task :foo:jar and its task dependencies, if foo is a project dependency of bar. You can disable this behaviour with the Gradle command line options -a or --no-rebuild or the following entry in your settings.gradle:
startParameter.buildProjectDependencies = false

Complex packaging in gradle for servers with different binaries

I have the following dependency structure
prodwebserver -> prod.jar -> transitive prod dependencies
devwebserver -> prodwebserver.jar, runtimeCompiler.jar, dev-router.jar -> more transitive dependencies
My devwebserver 'will' have ZERO source code. In gradle, currently I have a target called embeddabledevwebserver which depends on those.
Now I need to package up a release into a format of
release
|
|--prod - contains all prod jars
|
|--development - contains ONLY the extra jars that prod is missing
How can I get the difference in jar sets between the two targets such that I only put the extra jars needed for development in the development directory?
(this is nitpicky and not too important) Is there a way I can do this without having this empty embeddabledevwebserver project which is sort of an annoying shell project?
My actual current build file ...(WIP)...
https://github.com/deanhiller/webpieces/blob/gradlePackaging/build.gradle
(comments on that file welcome and appreciated)
EDIT: More specifically, I have these sections to start copying/syncing files over
task stageTemplate(type: Copy) {
from '.'
into buildDir
include stagingDirName + '/**'
}
task stageWebServer(type: Sync, dependsOn: [':embeddablewebserver:assemble', 'stageTemplate']) {
from childProjects.embeddablewebserver.toStagingDir
into new File(outputStagingDir, 'prod')
}
task stageDevServer(type: Sync, dependsOn: [':http-router-dev:assemble', 'stageWebServer']) {
from childProjects['http-router-dev'].toStagingDir
into new File(outputStagingDir, 'development')
exclude stageWebServer
}
and I can't exclude stageWebServer from stageDevServer but basically for all the jars that stageWebServer task moved over, I want to filter out all the jars with those same names for the development one.
thanks,
Dean
ok, I finally worked through this adding println to print every object and got to this which works for copy at least...I am not sure if Sync is fully working(ie. if I remove a file from prod and it is still in development, will it show up or not).
task stageWebServer(type: Sync, dependsOn: [':embeddablewebserver:assemble', 'stageTemplate']) {
from childProjects.embeddablewebserver.toStagingDir
into new File(outputStagingDir, 'prod')
}
task stageDevServer(type: Sync, dependsOn: [':http-router-dev:assemble', 'stageWebServer']) {
from childProjects['http-router-dev'].toStagingDir
into new File(outputStagingDir, 'development')
exclude { details ->
def fileNames = stageWebServer.source.collect{ entry -> entry.getName()}
fileNames.contains(details.file.getName())
}
}

Resources