I have this kotlin gradle build script representing my use case.
I am working with Gradle 6.7.
This is my kotlin gradle build file:
plugins {
java
}
tasks.register("createFile"){
doLast{
projectDir.resolve("tmp.txt").createNewFile()
projectDir.resolve("tmp.txt").writeText("tmp")
}
dependsOn("assemble")
}
tasks.register("createExecFile", Exec::class){
workingDir(buildDir)
commandLine("cmd", "/c", "mkdir destdir\\subdir")
dependsOn("createFile")
}
tasks.register("copyBug", Copy::class){
from(projectDir.resolve("tmp.txt"))
into(buildDir.resolve("destDir"))
dependsOn("createExecFile")
}
Now run gradle copyBug -i.
The first time this will give you this output:
> Task :copyBug Deleting stale output file: E:\repo\BugCOpy\build\destDir Caching disabled for task ':copyBug' because: Build cache is disabled Task ':copyBug' is not up-to-date because: No history is available.
The copy task deletes the file created by the previous exec task.
Now if you rerun this command the copy task won't delete stale file.
So what are those stale file? How can I prevent those file to be deleted? My first build and is different than the other build.
Should I file a bug?
In your createExecFile task you produce output files without telling Gradle about them. So Gradle doesn’t know that this task and the copyBug task use the same output directory. Instead, Gradle believes that copyBug is the only task producing outputs under build/destdir and hence it’s safer to assume that any existing files in that directory should not be there (and are “stale”).
The solution is to tell Gradle that your createExecFile task outputs to build/destdir:
tasks.register("createExecFile", Exec::class) {
workingDir(buildDir)
commandLine("cmd", "/c", "mkdir destdir\\subdir")
// tell Gradle about the output directory
outputs.dir(buildDir.resolve("destdir"))
dependsOn("createFile")
}
See this release notes section for why this behavior was introduced and this explanation to a very similar issue if you want some more background information.
My build process looks like
run gradle (part 1)
do something else
run gradle (part 2)
For me annoyingly running gradle in step 3 would not just add a few files to the output directory but delete that folder as stale first. Even adding
outputs.dir(...)
did not prevent Gradle from removing it as stale. Working out the inputs and outputs of my task looked too tedious, but luckily I found a way to tell Gradle not to perform any up to date tracking:
Example 37. Ignoring up-to-date checks mentions to add
doNotTrackState("Comment why this is needed")
which ultimately helped me to keep the files from build step 1.
I'm starting to use gradle on my projects and I want to automatic install the file generated after build.
I tried to search, but didn't found.
How to move the .jar from build/libs to another paste, something like c:\server\plugins
I tried this code, but did't work
task deploy(type: Copy, dependsOn: ['build']) {
from 'build/libs'
into "c:/server/plugins/"
}
Here my build.gradle: http://pastebin.com/nwwdq0wd
Edit:
Did't work means the build file is not being copied/moved to where I want to
I just did the folowing command and worked. Thanks #JBNizet
gradle deploy
How does Gradle store downloaded jar files on the local file system? Maven stores them in the .m2 directory under USER_HOME, but where does Gradle store them? I checked the .gradle folder there, but saw only compiled scripts.
On Mac, Linux and Windows i.e. on all 3 of the major platforms, Gradle stores dependencies at:
~/.gradle/caches/modules-2/files-2.1
Gradle caches artifacts in USER_HOME/.gradle folder. The compiled scripts are usually in the .gradle folder in your project folder.
If you can't find the cache, maybe it's because you have not cached any artifacts yet. You can always see where Gradle has cached artifacts with a simple script:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.guava:guava:12.0'
}
task showMeCache doLast() {
configurations.compileClasspath.each { println it }
}
Now if you run gradle showMeCache it should download the dependencies into the cache and print the full path.
In Windows 10 PC, it is saved at:
C:\Users\%USERNAME%\.gradle\caches\modules-2\files-2.1\
Gradle's local repository folder is:
$USER_HOME/.gradle/caches/modules-2/files-2.1
Defined dependencies will be loaded from remote repositories into gradle's local repository folder. For each loaded file, gradle will be create a new folder named with md5 value of the original file (pom,jar,..). Full path for the dependency file is made up from :
groupid + artifactid + version + FILE_MD5_VALUE + FILE_NAME
If our defined dependency is:
compile 'org.springframework:spring-jdbc:4.3.4.RELEASE'
Then the library will be loaded into :
/$USER_HOME/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jdbc/4.3.4.RELEASE/42175d194cf6aa7c716c0887f30255e5c0a5262c/spring-jdbc-4.3.4.RELEASE.jar
In fact the cache location depends on the GRADLE_USER_HOME environment variable value.
By default, it is $USER_HOME/.gradle on Unix-OS based and %userprofile%.\gradle on Windows.
But if you set this variable, the cache directory would be located from this path.
And whatever the case, you should dig into caches\modules-2\files-2.1 to find the dependencies.
If you want your dependency files to be in some specific folder you can simply use a copy task for it. For Eg.
task copyDepJars(type: Copy) {
from configurations.compile
into 'C:\\Users\\athakur\\Desktop\\lib'
}
I am on windows,
You should be able find the dependencies inside
$USER_HOME.gradle\caches\artifacts-24\filestore
Many answers are correct!
I want to add that you can easily find your download location with
gradle --info build
like described in https://stackoverflow.com/a/54000767/4471199.
New downloaded artifacts will be shown in stdout:
Downloading https://plugins.gradle.org/m2/org/springframework/boot/spring-boot-parent/2.1.7.RELEASE/spring-boot-parent-2.1.7.RELEASE.pom to /tmp/gradle_download551283009937119777bin
In this case, I used the docker image gradle:5.6.2-jdk12.
As you can see, the docker container uses /tmp as download location.
You can use the gradle argument --project-cache-dir "/Users/whatever/.gradle/" to force the gradle cache directory.
In this way you can be darn sure you know what directory is being used (as well as create different caches for different projects)
I just stumbled onto this while searching for this answer. If you are using intellij, you can navigate to the file location, but opening the external lib folder in the project explorer, right clicking on the jar, and select Open Library Settings.
It took me a while to realize this, hence the additional answer. Hopefully it can save folks time. Note that if you are running sudo gradle the dependencies may not be in your home directory, even if sudo echo $HOME returns /Users/<my-non-root-user>/. On my Mac, Gradle was caching the dependencies in /private/var/root/.gradle/caches/.
In case it is an Android gradle project - you can find the android libraries below your $ANDROID_HOME/extras/android/m2repository folder
In android studio do the following steps to check the gradle downloaded jar file.
Set project structure view to "Project"
At bottom External library section available, expand it.
Here you can see downloaded jar files.
On my windows machine with "Buildship 2.0.2" plugin installed in eclipse, dependencies are stored :
$USER_HOME.gradle\caches\modules-2\files-2.1
For my case, I was using an Ivy repository, and my Gradle dependencies were stored in ~/.ivy2/.
How would I copy dependencies to somewhere in the project folder with Gradle?
I've setup SBT to do this, but I'm not sure about Gradle
Your use case makes a big impact on the ways you could do this. But, answering generically you could do something like the following to copy from a collection to a directory.
task copyDeps(type: Copy) {
from configurations.runtime
into "${buildDir}/deps"
}
Tweak to meet your use case. If you are trying to create a Java application take a look at the application plugin.
Problem Description
Consider the case maven is being used on hudson.
Now someone took checkout of a project,modified some files but accidently used same artifact id and version number(non snapshot).
He/She then build this project on hudson and did maven install.The modified artifact is now in hudson .m2 . Any other project which depent on it will be build with modified artifact. No one finds this out if compilation doesn't fail. Even though correct artifact resides in central repository it is never used because modified one is picked up from .m2 when hudson starts building.
So i am looking for a way to prevent this accidental human error.
Anyway to revoke permissions of maven install on non snapshot versions (released artifacts) on hudson ?
Any way to compare checksums of .m2 in hudson and on in remote central repository so that checksum failures can generate warnings or fail build ?
I have already checked that there is no way to force update non-snapshots versions from central repository as they are meant to be immutable.
Purging central repository or using separate repository for each job on hudson will result in increased build times & disk space usage respectively.
Any help would be appreciated.
I don't think you're going to find a way to stop an install from overwriting an artifact. A repository server should have a setting to prevent deploying an updated release artifact though. See, for example, "How do I disable artifact redeployment" for Nexus.
Here is how we manage versions in our project:
We work on a SNAPSHOT version. On Jenkins, we have a Fast Build job that builds and tests this application, but fails if the version is not a SNAPSHOT. This is done by a custom enforcer (this is the opposite of the require release version enforcer).
When we want to make a release, we use a Jenkins job for that. Using the parameterized build, and Maven release plugin, the person who is in charge of doing the release will just indicate the version of the release (the stable version), the next SNAPSHOT version, as well as the name of the SCM tag. Thus, only Jenkins will define a stable version and the developers will always work on a SNAPSHOT code.
But of course, this does not prevent the developers to make what he wants on his local machine. But we always consider one trusted place: the Jenkins server. It works on my machine is never a good answer to a problem ;o)
There was no direct way to solve this but we solved this inderctly by writing a cron-job which runs every five minutes and marks all the jars which are NON-SNAPSHOT as read only in the local repository of Hundson . In this way when some project in Hudson tries to overwrite it my mvn install or mvn deploy it fails in overwiriting the artifacts as they are readonly.
Any new artifacts to be realeased can easily be written. Once written within next five minutes script marks them as read only.
Here is code for unix script permission-handler.sh
#!/bin/bash
cd ~/.m2
date 2>&1>> permission-handler.out
find . -name '*jar' -type f | grep -v 'SNAPSHOT' | xargs chmod -vc 444 2>&1>> permission-handler.out
chmod 777 permission-handler.out
Logging is also handled to see which all artifacts have been marked as released only.
This is solved by configuring your Maven repository (e.g. Nexus, Artifactory) from not allowing overwrite of the release repos. In Nexus we have a repo for SNAPSHOT and one for releases. The SNAPSHOT repo allows overwrite. But the release repo does not allow overwrite. This is just a simple checkbox feature in Nexus for that repo. Once a release version is put in the repo, it cannot be overwritten. Works out very well.
I had the same requirement.
Checking for the artifact can be achieved with REST request from a gradle task.
publish.dependsOn lookForArtifacts
task lookForArtifacts {
group "upload"
doLast {
def pomFileName = "${ARTIFACT_ID}-${ARTIFACT_VERSION}.pom"
def artifactPath = "${ARTIFACT_GROUP.replace(".", "/")}/${ARTIFACT_ID}/${ARTIFACT_VERSION}/${pomFileName}"
def repositoryUrl = "$MAVEN_SERVER/${artifactPath}"
println("# searching for existing artifact wit id ${ARTIFACT_VERSION}")
println("")
if (urlExists(repositoryUrl)) {
println("# Existing artifact found")
println("")
throw new RuntimeException("Artifact with version $ARTIFACT_VERSION already exist - increase the verion to publish")
} else {
println("# No existing artifact found. Preceding to publish")
println("")
}
}
}
def urlExists(String repositoryUrl) {
try {
def connection = (HttpURLConnection) new URL(repositoryUrl).openConnection()
connection.setRequestProperty("Authorization", "Basic " + getBase64EncodedCredentials())
connection.setConnectTimeout(10000)
connection.setReadTimeout(10000)
connection.setRequestMethod("HEAD")
def responseCode = connection.getResponseCode()
if (responseCode == 401) {
throw new RuntimeException("Unauthorized MavenUser user. Please provide valid username and password.")
}
return (200 == responseCode)
} catch (IOException ignored) {
println(ignored)
return false
}
}
def getBase64EncodedCredentials() {
def s = "$MAVEN_USERNAME" + ":" + "$MAVEN_PASSWORD"
return s.bytes.encodeBase64().toString()
}