Any chance I can have `.yaml`s instead of `.proper...
# community-support
v
Any chance I can have `.yaml`s instead of
.properties
that's easily read by gradle? the flatness of properties tripes me up when it becomes larger
v
For what exactly?
v
build level company specific config stuff technically the properties work, i just like the indentations of yaml
v
well, then just use a yaml that you parse with any yaml parser or serializer like
kaml
or
SnakeYAML
/
SnakeYAML KMP
Or maybe there is some 3rd party plugin providing that functionality
v
I see, thank you!
v
If there is no 3rd party plugin you find and you do it yourself and it is about multi-project build where you want the values everywhere, you most likely want to use a shared build service to only parse the file once per build run and either take the parsed values from that service directly, or additionally have some convention plugin that registers an extension that provides the parsed values conveniently and is wired to the build service parse result.
v
yes that swhat I intend to do, but I want the values to be changeable by the consuming projects so I dont want to hardwire it into the plugin
v
Yes, if it were hard-coded, you wouldn't need a service to parse a file or similar
v
would you however model the exposed "thing" which is hierarchical, as a data class and inside it references to other data classes or should be this provider of providers etc
v
I meant having some
our-fancy-config.yaml
in the consumer project and in your convention plugins you parse that file with the service and provide the result from there directly, or through an extension.
would you however model the exposed "thing" which is hierarchical, as a data class and inside it references to other data classes
or should be this provider of providers etc
Not fully sure without more context, but I guess just data classes would be fine
Especially if those are static (in the scope of one build execution) values, and not something configurable
v
Copy code
config.appA.baseApiUrl=..
config.appB.baseApiUrl=..
config.appC.baseApiUrl=..
something like this is the source
Copy code
data class Config(appA: AppA, appB: AppB, appC: AppC)
data class AppA(baseApiUrl: String)
...
v
While having providers might make sense, if it is typical that the consumer will map those values, but he could always use
providers.provider { ... }
then if he want's to do it only when needed.
v
i.e. plain data classes or should
appA
be a
Provider
instead
v
If the values would come from some task execution potentially then it would be different, so that you can carry on the task dependency.
As I just described, I guess as those are static values just plain data class should probably be fine.
thank you 1
v
yes, its just a bag of consts, changing urls based on environments etc
about reading the .properties however,
Copy code
Provider<Properties> customProperties = providers
    .fileContents(customPropertiesFile)
    .asText
    .map { text ->
        def properties = new Properties()
        properties.load(new StringReader(text))
        return properties
    }
this means any time I access this, it reads the file, i.e. does IO?
v
As
.map
is evaluated each time you query the value, yes. Unless you for example make a property to which you set this provider as value and then call
finalizeValueOnRead()
on it, then it is only evaluated once. Basically a poor-man's version of the memoizing providers requested at github.com/gradle/gradle/issues/25550. But that's anyway not what I recommended. I recommended having a build service that does the parsing in its constructor, because the scope of a build service is one build execution. So you do the parsing once and then have alle the values accessible from the service or if you need them conveniently in the build scripts and anyway have some convention plugin applied everwhere then additionally an extension that gets its values fed from the build serivice.
v
whats a build service, gradle feature?
v
yes
v
about the rereading, is that a problem or not? i mnot sure how should that play with configuration cache, make me think that changing props doesnt trigger invalidation?
v
It has various uses. It can be used to ensure some tasks are not run in parallel even if CC is used and they could run in parallel, or to boot up some test server or similar before running test if actually really running tests and shutting it down afterwards, or to parse a file once in a build invocation, ....
about the rereading, is that a problem or not? i mnot sure how should that play with configuration cache, make me think that changing props doesnt trigger invalidation?
If you parse the file at configuration phase, it becomes a CC input and thus will invalidate the CC entry if the file was changed. If you only parse the file at execution phase, it does not influence CC state and thus would not be a CC input and the CC entry could be reused.
v
aaand should it? 😄 i dont know, its just constants I feed into android's buildconfig mostly
v
Or if you do the file parsing inside a value source, then only what the value source returns becomes a CC input if you actually query the value source at configuration phase.
aaand should it? 😄 i dont know, its just constants I feed into android's buildconfig mostly
I don't do Android, so no idea. But probably yes, you probably configure some task with those values, so different file content means different task config, so the CC state cannot be reused and needs to be reevaluated.
v
and about the rereading, how big of a issue is that? if I have a callsite which will access 2 properties, so I just
.get()
the whole config into a local variable and reference that, i.e. not completely requerying, but if another build script tries to do that, i.e 2nd io, is that...fine?
v
Up to you. You can also parse the file 20 times if that is fast enough for you. But file-io is a rather slow task and I personally would avoid it wherever possible, especially during daily-work running, there a Gradle build should optimally be as fast as possible. If you waste 5 seconds for each build invocation and have 50 developer colleagues that run 100 builds a day, then you waste 7 hours working time each day and decrease developer happiness. If you are the only person working with that and run 2 builds a day, you waste 10 seconds and maybe don't care about the lost 10 seconds per day.
v
I see, so it is possible to cache the config instance in nemory across build projects - and its the build service thing?
v
I don't understand what you mean, but the answer is no 🙂
The build service lives for one build execution. In your case it would be useful to parse the file contents only once even if you need values in multiple places, especially in multiple projects of the same build.
Oh, wait, maybe I misread your last sentence and the answer is yes
Imagine it (for the usage in your case) like
Copy code
val value1 = doCostlyCalculation().getValue1()
val value2 = doCostlyCalculation().getValue2()
vs.
Copy code
val values = doCostlyCalculation()
val value1 = values.getValue1()
val value2 = values.getValue2()
Where value1 and value2 are needed in different projects of the build
thank you 1