I’ve been reading Configuration Cache Requirements for your Build Logic a lot, and I’m having a hard time following some parts of it. Here is what I mean:
- Clear part: Running External Processes
Here you say, *.execute() shouldn’t be used in configuration time, but if I must, then I should use a compatible API like providers.exec { commandLine("git", "--version") }.standardOutput.asText.get(). Nice and clear.
- Slightly confusing part: Reading System Properties and Environment Variables
I had to read this a few times to understand what you mean. The docs say:
In general, you should avoid reading the value of system properties and environment variables at configuration time to avoid cache misses when these values change. Instead, you can connect the Provider returned by providers.systemProperty() or providers.environmentVariable() to task properties.
I get the part that env vars can cause the configuration cache to be invalidated. That’s okay, if we use it responsibly, right? Because I think there is a confusion about whether we are allowed to use System.getenv('MY_VAR') or we should use something else like providers.environmentVariable('MY_VAR').get() in case we need the value in configuration time.
And then, for example you warn that System.getenv().findAll { ... } is a problematic pattern, and if we need to use something like that, at least we should use providers.environmentVariablesPrefixedBy("JDK_"). However, that’s not the same code, because now you got a provider. You no longer .get() it like in the case of running git --version. I understand that if possible, we should connect such providers to the task input, but what if we can’t, and we need to read the value in configuration time? Right now I can’t come up with a specific example though, and therefore I would like to keep this conversation in theory level.
- More confusing part: Undeclared Reading of Files
The docs say:
Plugins and build scripts should not read files directly using the Java, Groovy or Kotlin APIs at configuration time. Instead, declare files as potential build configuration inputs using the value supplier APIs.
But once again, the examples are misleading, because providers.fileContents(layout.projectDirectory.file('some.conf')).asText is not the same as def config = file('some.conf').text. The problem is the same as in the previous point, but now with even less information on “what if I need the value in configuration time?” So this time, I can’t even tell: is it safe to use the original API, or am I supposed to use the provider-based API, but then is it okay to .get() it in configuration time?
It would mean a lot to me if you could clarify these questions for me.
Thanks in advance!