Closed viktornordling closed 9 years ago
The plugin was only designed to add new files to the Gradle property processing mechanism, it doesn't do anything more than that. What I do in my projects is create a task named prep
that copies my template files into the resource directory. I then make compileJava
depend on prep
. This way, I always get fresh copies of any files that would be affected by the environment I'm using.
If I was generating files, and that step was expensive timewise, I'd simply skip the compileJava
dependency and make sure to run it manually whenever I needed to build for a different environment.
Thanks Steve,
But does that mean you can't switch environment without manually deleting the files first?
//V
1.When i run copy task using filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: project.filterTokens) 2.Copied files are filtered and values like @myProperty@ are overwrited. 3.Change the environmentName and run the task again. 4.The task is UP-TO-DATE and filter values are same as in point 2.!
Related to bug: https://issues.gradle.org/browse/GRADLE-1646
@viktornordling I've made my compileJava
task depend on prep
. The prep
task is never up to date, so it copies files every time I do a build, so you can safely switch environments at will.
However, I was thinking about this recently, and I realize that this would in turn mean that compileJava would never be up to date, and this means a lot of unnecessary compilation. In our case this is not a big deal, but for larger projects this would be an issue. The solution to this might be to create a prep
task that is smarter about when things have changed. I don't think this is a plugin issue since it doesn't know how properties will be used, but if I find a smarter way to create the prep
task, I'll update this issue with the solution.
@asaarnak I do my copies with a separate prep
task, which is never up to date, so I always get the right values. This can slow down the build, but it would be accurate.
I did notice that you used project.filterTokens
. My task is using project.ext.filterTokens
I would doubt that this would make any difference, but it might be worth trying...
I've made some enhancements to 1.4.3-SNAPSHOT that might help out with these issues.
The plugin creates 4 methods in every task that can be used to enforce the presense of properties at run time. I've enhanced these methods to register the properties as task inputs.
For example, consider the following task:
task prep() {
description = 'Copy resources and files needed for building'
requiredProperties 'appLogLevel', 'defaultLogLevel', 'logFilePrefix'
outputs.file new File(resourceDir, 'log4j.properties')
doFirst {
copy {
from templateDir
include 'log4j.properties'
into resourceDir
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: project.ext.filterTokens)
}
}
}
This task will fail if we don't define values for the 'appLogLevel', 'defaultLogLevel', and 'logFilePrefix' properties. If the properties are present, the task will copy a log4j.properties file, making token substitutions along the way. The task registers the log4j.properties file as a task output and the plugin now registers the 3 properties as task inputs, so if you run the prep
task twice, it will be considered up to date. If the value for any of the 3 properties should change, the task will no longer be considered up to date and will make a new copy of the log4j.properties file.
You can include the latest SNAPSHOT release of the plugin by adding the Sonatype Snapshot repo to your build.gradle. I'd be interested to know how this works for you before I release this to the general public.
I solved the issue thanks to http://stackoverflow.com/questions/16154042/gradle-force-custom-task-to-always-run-no-cache.
The trick is to add: prep.outputs.upToDateWhen { false }
Not sure why your prep task is never up to date Steve?
I looked into this over the weekend. My prep task was never up to date because it didn't declare any inputs or outputs. I've enhanced the plugin to declare inputs, and the task from my last comment declares outputs, so the up to date checking now works as I would expect. upToDateWhen {false}
works if you want to force the file copy every time.
Thanks Steve,
That's cool that your task detects changes now. Wouldn't there be an issue though were the files actually don't change, only the environment does? So if I change from dev to prod, no input files have changed on disk, just the flag, if that makes sense?
Regardless, would you care to share what your updated task looks like?
I also still don't understand why previously your task was never up-to-date, when for me and asaarnak the task is always up-to-date?
My original prep task didn't declare any outputs, and I found a bit in the Gradle documentation that said that a task that doesn't declare any outputs is never up to date.
In addition to outputs, a task uses inputs to determine if anything changed that effects the task. My original prep task didn't declare any inputs either, further adding to my problem.
I made a change to the plugin to declare as inputs any property mentioned in the requiredProperties
method (and the 3 others from the plugin documentation), and I added an output to the task. My updated task is the one in the comment 4 posts up. The important bits are requiredProperties 'appLogLevel', 'defaultLogLevel', 'logFilePrefix'
, which tells the plugin that 3 properties are required, and that they should be inputs to the task, and outputs.file new File(resourceDir, 'log4j.properties')
which tells the task that it is producing a log4j.properties file.
Since the task now watches the 3 required properties, if any one of them changes for any reason, the task will no longer be up to date. So if you change environments, the task re-runs.
If you use the snapshot version of the plugin, you could try it out. I'd be curious as to how it works for you before doing an official release.
I'm not sure why asaarnak's task was always up to date without seeing it, but I was under the impression that he was copying files as part of another task that had its own inputs and outputs that caused it to be up to date, but that those inputs and outputs had nothing to do with the properties or the files he was copying. That would cause the task to always be up to date.
Thanks Steve,
It's still not working the way you describe for me. If I remove the prep.outputs.upToDateWhen { false }
line my task is always up-to-date, despite declaring requiredProperties. Perhaps we are on different versions of Gradle and this behaviour has changed in between? I am currently on 1.11..
Ah, I see now, the task.inputs.property(propertyName, propertyValue)
was only added in the SNAPSHOT version, so that's why it's not working for me. Unfortunately I can't test with this version because of some incompatibilities between versions. I first got an error due to the Groovy version, and when I fixed that I got this rather cryptic error:
10:22:03.405 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.lang.IncompatibleClassChangeError: the number of constructors during runtime and compile time for net.saliman.gradle.plugin.properties.FileType do not match. Expected -1 but got 2
10:22:03.406 [ERROR] [org.gradle.BuildExceptionReporter] at net.saliman.gradle.plugin.properties.FileType.$INIT(FileType.groovy)
10:22:03.406 [ERROR] [org.gradle.BuildExceptionReporter] at net.saliman.gradle.plugin.properties.FileType.<clinit>(FileType.groovy)
10:22:03.407 [ERROR] [org.gradle.BuildExceptionReporter] at net.saliman.gradle.plugin.properties.PropertiesPlugin.buildPropertyFileListFromProject(PropertiesPlugin.groovy:206)
10:22:03.407 [ERROR] [org.gradle.BuildExceptionReporter] at net.saliman.gradle.plugin.properties.PropertiesPlugin.this$2$buildPropertyFileListFromProject(PropertiesPlugin.groovy)
Anyway, I can make it work manually by adding task.inputs.property
calls. Thanks.
That is a strange error. I'm not sure what it is, but I added a sourceCompatibility and targetCompatibility of 1.6 to rule out JVM issues and did a clean and build to make sure all class files were recompiled. Does the snapshot work now?
Did you forget to push?
I pushed to Maven's snapshot repo, but it sometimes takes a bit to show up. I just pushed the build.gradle changes in case you were building the artifact yourself. Does it work now?
I just released version 1.4.3 to production, and it is now available on the Gradle plugin portal. It should be on Maven Central shortly.
Hi,
Thanks for creating this plugin, it looks awesome so far!
One question, if I switch from one profile to another, my generated files aren't overwritten. Is this expected or is there a way to override this behaviour?
Cheers!
//V