Gradle: Force Custom Task to always run (no cache)
You can achieve this by setting outputs.upToDateWhen { false }
on the task.
This can be performed in your build.gradle
file:
handleManagementArchive.outputs.upToDateWhen { false }
It can also be done in the constructor of your custom task.
ResolveProjectArchiveDependency() {
outputs.upToDateWhen { false }
}
Jonathan Deon
Professional Software Developer based in Boston, MA, USA. Professional experience with Scala, Spark, Java technologies, SQL/Databases, Javascript, front-end technologies (HTML/CSS), various web services.
Updated on June 13, 2020Comments
-
Jonathan Deon almost 4 years
I wrote up a custom Gradle task to handle some dependency resolution on the file system where the paths are configurable. I want tasks of this type to always run. It seems though they only run once, I'm guessing because the inputs never seem to change.
I am aware of using
configurations { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' }
to effectively disable the cache, but I only want it to apply to very specific tasks. Also am aware of--rerun-tasks
command line prompt, which is also similar. Neither feel like the best solution, there must be a way to set this up properly in the custom task definition.Follows is my current implementation. I also had a version prior where the first 3 def String statements were instead @Input annotated String declarations.
class ResolveProjectArchiveDependency extends DefaultTask { def String archiveFilename = "" def String relativeArchivePath = "" def String dependencyScope = "" @OutputFile File outputFile @TaskAction void resolveArtifact() { def arcFile = project.file("dependencies/"+dependencyScope+"/"+archiveFilename) def newArcFile = "" if(project.hasProperty('environmentSeparated') && project.hasProperty('separatedDependencyRoot')){ println "Properties set denoting the prerelease environment is separated" newArcFile = project.file(project.ext.separatedDependencyRoot+relativeArchivePath+archiveFilename) } else { newArcFile = project.file('../../'+relativeArchivePath+archiveFilename) } if(!newArcFile.isFile()){ println "Warn: Could not find the latest copy of " + archiveFilename + ".." if(!arcFile.isFile()) { println "Error: No version of " + archiveFilename + " can be found" throw new StopExecutionException(archiveFilename +" missing") } } if(!arcFile.isFile()) { println archiveFilename + " jar not in dependencies, pulling from archives" } else { println archiveFilename + " jar in dependencies. Checking for staleness" def oldHash = generateMD5(new File(arcFile.path)) def newHash = generateMD5(new File(newArcFile.path)) if(newHash.equals(oldHash)) { println "Hashes for the jars match. Not pulling in a copy" return } } //Copy the archive project.copy { println "Copying " + archiveFilename from newArcFile into "dependencies/"+dependencyScope } } def generateMD5(final file) { MessageDigest digest = MessageDigest.getInstance("MD5") file.withInputStream(){is-> byte[] buffer = new byte[8192] int read = 0 while( (read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } } byte[] md5sum = digest.digest() BigInteger bigInt = new BigInteger(1, md5sum) return bigInt.toString(16) } }
Here's an example of usage of the task:
task handleManagementArchive (type: com.moremagic.ResolveProjectArchiveDependency) { archiveFilename = 'management.jar' relativeArchivePath = 'management/dist/' dependencyScope = 'compile/archive' outputFile = file('dependencies/'+dependencyScope+'/'+archiveFilename) }
-
Steinar over 5 years@Nick Thanks for the link to this interesting blog entry. As pointed out there, this is not the proper mechanism for rerunning tests. The question here though was about getting a custom task to always run. If the task uses other results from the build cache, those tasks will not be executed, but as far as I understand, this task will.
-
Ali Hidim over 5 yearsGood point, if you're sure the task itself isn't cached then it should be okay. I'm never sure what tasks the cache will cover so I like to use something that works everywhere!