Gradle build succeeds even though dependencies can't be downloaded - maven

We are new to Gradle and dependency resolution. I am in the process of creating pom.xml files for all our internally-generated artifacts and want to set up a job in our Jenkins server to verify the dependencies are properly defined and not conflicting (i.e. LibA requires x-1.0.jar, LibB requires x-1.1.jar, and AppY requires both LibA and LibB).
As such, I've set up a dummy project in SVN that simply includes a bunch of our internal artifacts as dependencies. Following TTD, I intentionally included some errors in the declarations (i.e. group and name, but not version). Sure enough, those dependencies can't be found.
But when I run this build with gradle (i.e. gradle dependencies) it includes all the failure messages but still says the build succeeded! Not good!
How can I, using Gradle/Jenkins, set up an automated job that will verify all dependencies are found?

There is no built-in task that resolves all dependencies and fails if a dependency isn't found. (IDE tasks are graceful in case of missing dependencies.) But you can easily write your own:
task resolveDependencies {
doLast {
configurations.all { it.resolve() }
}
}

gradle dependencies by design displays Gradle project dependencies reporting (if applicable) if given dependency cannot be resolved (a red text FAILED next to an unresolved dependency). To get an error use some task that depends on resolving dependencies for given configuration(s) like gradle check.
Updated. Gradle is smart in determining if given tasks are required to be executed. Therefor in case there is no source files to compile (compilation requires dependent classes/JARs to be resolved) gradle check can notice that executing compileJava/compileTestJava tasks is not needed (tasks are skipped as up-to-date). You can force it by adding any Java source file into src/main/test (tests requires also production dependencies (from compile configuration)).
This is just a workaround, there is probably a better way to do that (and I hope someone else will present it here).

Related

Error: DefaultOperationDescriptor#2b878eea already available in Android Studio

Failed to complete Gradle Execution
When I try to Sync Gradle with Project Files, the error mentioned below appears
Android Studio version that I am using is 3.0.1, Gradle Build 4.1-all.zip
FYI, I have already tried ->Build->Clean Project and Invalidate Cache & Restart and one more thing is that there is no error in my code.
Message Error:
Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:mockableAndroidJar]
Error:Failed to complete Gradle execution.
Cause:
Operation org.gradle.tooling.internal.provider.events.DefaultOperationDescriptor#86028ba already available.
BUILD SUCCESSFUL in 8s
Information:1 error
Information:0 warnings
But When I try to Run on my Emulator
The error below appears
Message Error At Run Time
Information:Gradle tasks [:app:assembleDebug]
E:\Android Game App\app\build.gradle
Error:(1, 1) A problem occurred evaluating project ':Android Game App:app'.
Failed to apply plugin [id 'com.android.application']
Due to a limitation of Gradle new variant-aware dependency management, loading the Android Gradle plugin in different class loaders leads to a build error.
This can occur when the buildscript classpaths that contain the Android Gradle plugin in sub-projects, or included projects in the case of composite builds, are set differently.
To resolve this issue, add the Android Gradle plugin to only the buildscript classpath of the top-level build.gradle file.
In the case of composite builds, also make sure the build script classpaths that contain the Android Gradle plugin are identical across the main and included projects.
If you are using a version of Gradle that has fixed the issue, you can disable this check by setting android.enableBuildScriptClasspathCheck=false in the gradle.properties file.
To learn more about this issue, go to https://d.android.com/r/tools/buildscript-classpath-check.html.
Information:BUILD FAILED in 16s
Information:1 error
Information:0 warnings
Information:See complete output in console
Nothing found on Google! Any help would be highly encouraged???
The key to the problem is this line. Maybe due to a project.all in root build.gradle or you are using composite builds.
This can occur when the build script classpaths that contain the Android Gradle plugin in sub-projects,
or included projects in the case of composite builds, are set differently.
that mean in all yours build.gradle you have more than one this line
buildscript {
dependencies {
classpath "com.android.tools.build:gradle:x.y.z"
}
}
what this means is that with the introduction of Android Gradle Plugin 3.Y.Z and the new way of handling dependencies,
if you mix in the same project 2 projects with different plugin version (one with a 2.3 and other with 3.0.1) you will get dragons while compiling.
And this error it's a way to force developer to check it and opt-out once detected and solved.
how to solve it, first ensure you don't use a android gradle plugin below 3.0.1 and use the new dependencies configurations, and add this property on every gradle.properties you have.
android.enableBuildScriptClasspathCheck=false
with that you can now compile
one example could be found at realm sample repo they use a allprojects block that include android gradle plugin on every module. and solve it adding previus gradle property at root gradle.properties

How to use classes from a neighbouring subproject during configuration phase

I want to compile one subproject, then have those classes on the classpath while building the other subproject. (A custom tass would use classes created by the first one).
Currently I'm trying:
buildscript {
dependencies {
classpath project(':MyOtherProject')
}
}
... with the following result:
Cannot use project dependencies in a script classpath definition.
You cannot build something to be used to build the something. (something being the multi-project build here)
You either need to make the MyOtherProject a complete separate build, that you either install to some repository and then depend on it per coordinates or trigger that separate build during configuration phase or your build, then depending on its outcomes.
The other alternative is, that you put it into buildSrc project. This is a full multi-project build contained in your root project that is built and added to the classpath of the main build scripts automatically by Gradle and is meant for Plugins and Custom tasks that you do not want to use in other builds also and thus do not make them a separate build.

Declare tests to run without compiling sources

Consider such a situation: there's a big project, which takes tremendous time to compile and I'm having it's resulting artifacts as separate files (jar).
I want to run the unit tests on this project without compiling and jar-ing project itself, so I need to remove dependency on compileJava task, but this task is not in the dependsOn list of test task.
dependsOn property of test task contains only some [file collection] and if I'm printing this FileCollection.files, I'm getting the list of files and directories, which include .../build/classes/main. I think, after removing this entry, I'll get success in removing dependency on compileJava (as I understood, .../build/classes/main is just the result of running compileJava and that's why compileJava appeared). But I just don't understand, how to remove this entry.
By the way, in this case there's no problem of adding this jar to classpath, so that's not an issue.
I'm using Gradle 1.8.
Thanks.
compileJava will be up-to-date if nothing has changed, and jar isn't depended upon by test. If you nevertheless want to add the ability to run tests against a downloaded Jar, declare another Test task. (Reconfiguring test.classpath should work as well, but seems less desirable.)

Skip refreshing dependencies in gradle

Short version of question:
Is there a way of telling gradle not to resolve dependencies? I know I can skip single task with -x switch but resolving dependencies isn't performed though some task I guess, to I don't know how to do it.
Long version:
Right now I can run tests from gradle with simple 'gradle test' which performs gathering dependencies, building and running tests..
But I'd also like to run tests using gradle on some other machine which can't download dependencies from maven. I thought that I could just perform some packaging which would download all dependencies to some lib folder, and I could expand tests classpath (in that task) to this folder. The problem is, that gradle still tries to contact maven when I run 'gradle myTests'. Is there a way of preventing resolving dependencies for this single task?
There's the --offline flag. Alternatively, you can declare a flatDir rather than a maven repository whenever the build should be run with "local" dependencies.
For my use case, my internet is restricted so I would setup dependencies while I can still have full access. And when I'm restricted, go to Preferences, search for Gradle, and check "Offline work".
Of course I'll have to turn it back on whenever new dependencies are added.

Gradle Java plugin and Multi-Projects: Why does jar task doesn't depend on check?

According to http://www.gradle.org/docs/current/userguide/java_plugin.html and Figure 23.1, the jar task depends on the classes task.
In my scenario I have a multi project containing three projects - ProjectCommon, ProjectApp1 and ProjectApp2. ProjectApp1 depends on ProjectCommon, ProjectApp2 depends on ProjectCommon.
Here's the build.gradle of ProjectApp1 and ProjectApp2:
dependencies {
compile project(':ProjectCommon')
}
I wan't to build now only ProjectApp1, using
$ gradle :ProjectApp1:build
The output shows, that e.g. test and check of ProjectCommon is not executed:
:ProjectCommon:compileJava UP-TO-DATE
:ProjectCommon:processResources UP-TO-DATE
:ProjectCommon:classes UP-TO-DATE
:ProjectCommon:jar
:ProjectApp1:compileJava UP-TO-DATE
:ProjectApp1:processResources UP-TO-DATE
:ProjectApp1:classes UP-TO-DATE
:ProjectApp1:jar
:ProjectApp1:assemble
:ProjectApp1:compileTestJava UP-TO-DATE
:ProjectApp1:processTestResources UP-TO-DATE
:ProjectApp1:testClasses UP-TO-DATE
:ProjectApp1:test
:ProjectApp1:check
:ProjectApp1:build
BUILD SUCCESSFUL
Total time: 4.633 secs
ProjectApp1 is now built without knowing if ProjectCommon is really fine...
(of course I could do gradle :ProjectCommon:build :ProjectApp1:build instead to avoid this).
Wouldn't it be "safer", if jar would generally depend on check?
Or am I doing something wrong with the dependencies and I better should use in build.gradle of ProjectApp1 and ProjectApp2:
dependsOn(':ProjectCommon')
(which gives a deprecation warning)
The Gradle Java plugin uses project compile dependencies only for certain tasks, the check task is not one of them.
In ProjectApp1, add
check {
dependsOn ':ProjectCommon:check'
}
The jar task doesn't depend on the check task because they have no semantic dependency - the latter doesn't produce anything that the former consumes.
Wouldn't it be "safer", if jar would generally depend on check?
It would cost time without being any safer in some cases (e.g. Java compilation), and would not be safe enough in other cases (e.g. when publishing related projects, where you want all projects to be tested before publishing any of them). With Gradle, you can tailor the behavior to the particular needs.
The Java plugin provides a buildNeeded task, which fully builds upstream projects before building downstream projects. In a similar fashion, it would be possible to make Gradle test upstream projects before using their outputs in downstream projects. The question is how useful this would be.

Resources