How to cache and use gradle plugins locally? - caching

I am trying to build my application with limited access to internet with Gradle.
I was successfully able to use normal jars with
repositories {
mavenLocal()
...
and populating ~\.m2\repository with appropriate files.
But I also have statements like
plugins {
id 'org.hidetake.ssh' version '2.4.0'
}
in my build.gradle. When build, I get the following error
Error resolving plugin [id: 'org.hidetake.ssh', version: '2.4.0']
> Could not GET 'https://plugins.gradle.org/api/gradle/2.9/plugin/use/org.hidetake.ssh/2.4.0'.
> Connection to https://plugins.gradle.org refused
Apparently, Gradle is trying to get plugin from Internet, which is prohibited.
How can I cache this plugin?
On my another machine, which has full internet access, I found directories like
.gradle\caches
but it has some strange hash subdirectories, which I am not sure how to use. Copying of modules-2 directory from another machine didn't help.

I suppose, it's not possible with the new plugins DSL, because in that case, plugin is specified by it's global unique id and version, which are not stored in your cache.
You can use for that some local plugin repository with required additional Plugin Marker Artifact, read about it here.
Or just don't use plugins dsl and declare your dependencies in plain old way with apply plugin: 'plugin_name' and storing required jars in your local repository the same way, it's done with you project dependencies.

you add the file settings.gradle
pluginManagement {
repositories {
mavenLocal()
}
}
and now it will onlz try to resolve plugins from ~/.m2/repository/

Related

Cannot import com.tibco.tibjms.TibjmsQueueConnectionFactory with Gradle

so I've been working on migrating a Maven project over onto a Gradle one. While doing so, I can across a class called TibjmsQueueConnectionFactory that I've been trying to figure out how trying to import. I've found most of my other imports on MVNRepository however, none of the ones I try for this one seem to work.
This is basically all I'm trying to do:
// https://mvnrepository.com/artifact/com.tibco/tibjms
implementation group: 'com.tibco', name: 'tibjms', version: '1.0'
I did see somewhere that Tibco may not exist at that location at all, and maybe I'll have to download a jar file, but I'm not sure if this is the case or not. Has anyone else had this issue before? How did you resolve it?
A possible maven project pom dependency solution is available in this answer.
You can get tibjms-4.1 from pom uploaded in openmindonline repo which has TibjmsQueueConnectionFactory. We are not able to access other version from icm.
Add openmindonline repo information in your repositories block in your build.gradle
repositories {
// You can declare any Maven/Ivy/file repository here.
maven {
url "http://repository.openmindonline.it/"
}
}
Then add implementation 'tibco-ems:tibjms:version:4.1' in dependencies block.
If you have jar file available locally, you can follow solutions available in this question.

Publish reusable gradle tasks

I would like to publish some common parts of build.gradle file to be reusable in different projects (using apply from: url_to_file construction). To achieve this I've created a project called gradle-common that contains those common build files, with this build.gradle file:
group 'org.example'
version '0.1.0'
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
artifact source: file('files/first.gradle'), classifier: 'first'
}
mavenJava(MavenPublication) {
artifact source: file('files/second.gradle'), classifier: 'second'
}
}
repositories {
mavenLocal()
}
}
Files after publishing in maven repository there are files like:
gradle-common-0.1.0-first.gradle
gradle-common-0.1.0-second.gradle
And my question is: how can I remove version number from published artifacts and the classfier? For me ideal files would be:
first.gradle
second.gradle
There are many different answers to your question, but I think you are trying to create something that a plugin usually does without creating a plugin.
The best way to add functionality to multiple gradle projects is to create a plugin. You can also leverage Rules which this simple tutorial doesn't show, but you can inspect some of the gradle native plugins, such as maven-publish.
To answer your question, it is not possible to publish an artifact to a maven repository without a version. You have to download it with a version (you can use my-artifact:1+ to download the latest) and then strip the version yourself.
I am also wondering how are you planning to include these files to your specific gradle files. You won't be able to use them as dependencies, since the dependency resolution happens after the scripts are read. If you are downloading them somehow before the script runs, then you probably don't need a maven repository for that.

Is there a way to download a Gradle plugin from the repository to Gradle cache and use it in offline mode?

I am trying to create a copy of a gradle project that will work in --offline mode. I have automated all steps apart from one. I am not able to automatically download plugin jars into gradle cache.
My offline distribution works by specifying the GRADLE_USER_HOME, downloading all dependencies and bundling the whole gradle cache with the project. Unfortunately we are using a few custom plugins. I could of course make an exception for each one of them and include them manually, with some kind of if statement for the offline mode. But it would be great if I could simply download the jars into the cache.
Is there a way to force gradle to download all dependencies, including the plugin dependencies?
This is what I am doing for the rest of the dependencies:
task resolveAllDependencies {
doLast {
configurations.all { it.resolve() }
}
}
It downloads all dependencies to the local cache. But plugins are of course not included in any of the configurations.
It also seems that even if the plugin gets downloaded in the cache, it still fails in offline mode with the following message: Plugin cannot be resolved from https://plugins.gradle.org/api/gradle because Gradle is running in offline mode
Here's a working solution. It's not perfect, because it hard-codes the gradle plugin repository and changes the script. It's also much more verbose than the current way of using plugins.
Instead of the following simple plugin definition:
plugins {
id 'net.researchgate.release' version '2.3.5'
}
It's possible to define both the repository and the dependency manually and then use the plugin this way:
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'net.researchgate:gradle-release:2.3.5'
}
}
apply plugin: 'net.researchgate.release'
This downloads the plugin into the local gradle cache.

Gradle plugins DSL: Restriction on declaration location

I have a few Gradle scripts that get applied via apply from: 'my-build.gradle'. If I use the new plugins DSL as follows in the external build file my-build.gradle, it fails with the following error:
> startup failed:
Only Project build scripts can contain plugins {} blocks
See http://gradle.org/docs/2.3/userguide/plugins.html#sec:plugins_block
for information on the plugins {} block
Looking at the documentation pointed in the error message didn't reveal as to why the restriction is in place. Why is there a restriction on the location of the plugins declaration?
Files for reference below.
my-build.gradle file:
plugins {
id "net.saliman.cobertura" version "2.2.5"
}
build.gradle file:
apply from: "my-build.gradle"
// Other stuff
This is how you can use plugins in external Gradle files such as your my-build.gradle:
buildscript {
repositories {
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.sonarqube.gradle:gradle-sonarqube-plugin:1.1"
classpath "net.saliman:gradle-cobertura-plugin:2.2.8"
}
}
// Because this is a helper script that's sourced in from a build.gradle, we can't use the ID of external plugins
// We either use the full class name of the plugin without quotes or an init script: http://www.gradle.org/docs/current/userguide/init_scripts.html
apply plugin: org.sonarqube.gradle.SonarQubePlugin
apply plugin: net.saliman.gradle.plugin.cobertura.CoberturaPlugin
// rest of my-build.gradle omitted
Above I've activated the plugins for SonarQube and Cobertura.
Generally, to get the fully qualified class name of your plugin you will have to look inside its .jar file.
As for the technical reasons why you can't use a plugins {} block in an external file, I do not know. It might have to do something with the following:
[...] plugins [need to] be specified in a way that Gradle can easily
and quickly extract [them], before executing the rest of the build
script. It also requires that the definition of plugins to use be
somewhat static.
But rejoice:
Future versions of Gradle will remove this restriction.
I also faced similar issue recently and it got solved by changing Gradle settings in Intellij as follows:

How to publish in order to resolve latest.integration with gradle?

What I have is a maven repository (nexus) to which maven has been publishing. In each artifact version folder in my artifact repository folder there are the standard maven artifacts: a maven-metadata.xml, a jar, and a pom.xml, etc.
Now I want to resolve these using gradle. In my gradle.build file if I list them as:
dependencies {
compile group: 'com.company', name: 'artifact', version: '1.0-SNAPSHOT'
}
Then they will resolve correctly. However, I want to use the version "latest.integration" so that I can automatically integrate the latest versions of my dependencies. When I do this though, gradle fails to resolve it.
I imagine that gradle is looking for some ivy specific files that maven is not publishing up to the repository in order to resolve latest.integration, but I am not sure. Should I go back and re-publish all of my upstream dependencies with gradle before trying to resolve down stream? It would seem that since gradle supports maven repositories under the repositories element that it should already know how to interpret "latest.integration" for that repository type.
This is my repositories section:
repositories {
mavenCentral()
maven { url "http://<server>/nexus/content/repositories/snapshots" }
}
Thank you for any help you can provide
latest.integration is an Ivy concept, and only works for Ivy repositories. In other words, both publication and consumption would have to happen in an Ivy-compatible manner. (Gradle is capable of this; not sure about Nexus.)
The obvious alternative is to use Maven snapshot dependencies. What do you hope to gain from using latest.integration?

Resources