New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SOLR-16641 - Generate gradle.properties from gradlew #1320
Conversation
Hi @dweiss, |
There was some related discussion recently on SOLR-16634 -- at the moment I'm inclined to favor @dsmiley's suggestion to possibly move localSettings into the |
I've moved the generation of the localSettings to gradlew as discussed on the Jira issue. |
In reality, gradle folks are not really responsive to such requests... I know. I wish it was an option too. |
btw I wasn't intending to throw the scope of this PR by mentioning extracting Maybe it'd make sense to proceed with a different PR for the gradlew script quesiton? (sorry for the mixed messages). |
np. I don't mind doing a separate PR if it makes it easier to discuss and get the aabacb5 fix back in this one, or just let this one brew. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay; glad to see you working on this @colvinco ! It's a big deal! It'll improve the user getting-started experience (and even for experienced devs that forget localSettings LOL) and improve CI maintenance (e.g. working on Jenkins, GitHub Actions, crave.io). I think this PR/JIRA issue should more obviously declare this. It's a 100x more important than a "circular task dependency" in the build.
I'm surprised to see the "localSettings" gradle task live on. Surely it could be replaced with a bash script?
Depends. Some values there are computed from Java defaults. I agree a modification to launch scripts is probably easier to work with though, especially because it can pick up those defaults on the first run. |
It's also having to "write it twice" for the Windows .bat as long as it's still supported for dev. (Though with WSL becoming more prevalent that's a problem that will solve itself eventually). |
I suggest for the Windows side, just check if there is no gradle.properties and log a warning pointing at the unix script to help the user craft one themselves. This is just an idea; I think we can get away with being less thorough in some fashion for Windows as it's used much less and the need for this file is iffy. We're doing something rather unusual in Lucene & Solr -- insisting on gradle.properties when countless Gradle projects have no such mandate. A simplifying alternative would be to check gradle.properties into the project (but still marked ignored in .gitignore) and with Gradle's own defaults for number of workers & tests, or choose low ones. Advise users to edit them according to their machine. We are overthinking this stuff today! This has dev maintenance costs we pay right now. Generating this file is over-engineered IMO. |
I would create a I've taken a closer look at the properties file. Currently I see that only two of the settings are generated dynamically, and the rest are all hardcoded.
Getting the number of "processors" (depending on whether hyperthreading counts...) shouldn't be a problem on bash, https://stackoverflow.com/questions/6481005/how-to-obtain-the-number-of-cpus-cores-in-linux-from-the-command-line, so I could still seed in those values. I'm using Ubuntu in WSL:
For Windows it's also possible: https://pureinfotech.com/check-many-cores-processor-windows-10/
Doing the string replacement when copying the file in bash shouldn't be a problem, I'll see if I can do it sensibly in batch as well. |
Hopefully we're getting there now :) |
The check on crave.io is failing to apply my commit... I'm guessing that's because I've been force pushing to my branch and it's now a bit out of sync? https://github.com/apache/solr/actions/runs/4063490165/jobs/6995782967
I can create a clean PR on a fresh branch to test that, unless there's another reason for it to happen? |
It's been a bit of a rollercoaster ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this with some minor cleanup (optional)
buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
Outdated
Show resolved
Hide resolved
buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
var replacements = Map.of("org.gradle.workers.max", maxWorkers, "tests.jvms", testsJvms); | ||
|
||
// Java properties doesn't preserve comments, so going line by line instead | ||
// The properties file isn't big, nor is the map of replacements, so not worrying about speed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will work for simple values (and property names) but not when property values are more complex characters - these should (in theory at least) be escaped and/or encoded to plain ascii. I don't think it's a problem for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also not really happy with this parsing.
My idea would be: As the template is always applied (no problem with windows or any othe roperating system), we can make the template a real template and add two search/replace markers in the file. We should then load the whole file into a String (UTF-8 encoding!!!) and then do String#replace('@PLACEHOLDER@', value)
. Those replaces can be done using replacements.entries().forEach(e -> fileContent = fileContent.replace(e.getKey(), e.getValue())
(don't use replaceAll, as it uses regex and we have no forbiddenapis here to check this!!!!).
So I would add @MAX_WORKERS@
and @TEST_JVMS@
as map keys and replace those tags. This is like Ant did it for long time :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Local developer settings | ||
======================== | ||
|
||
The first invocation of any task in Solr gradle build will generate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is some value in leaving (some content) of this file under help/ - so that folks know that this file can be tweaked and is generated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And keep it wired into gradlew :helpLocalSettings
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry - I thought I removed that comment. This is duplicated in the template now so I think it's fine to be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah bad timing. I can revert that last commit I just put in, or leave it. It might still be a useful signpost
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment, I don't like the explicit parsing of the properties file. Just see it as a plain text template file and search/replace some ANT-like @VAR@
patterns in it: Load as string, replace tokens, save string (as UTF-8).
In general I am still not really happy with the whole setup. At moment in Lucene I have see this problem very often: You add some new features (like the MR JAR and adding new Java versions) and then many people have the template file expanded in their checkout and ten build fails, because it is not updated.
Not sure how to solve this without Gradle allowing to set some of the properties at runtime.
I have some ideas, but actually we should really open a bug reort that they finally fix the stupidness with toolkits, those properties files and allowing to set those properties in the gradle.settings file using code (which is committed to repo).
var replacements = Map.of("org.gradle.workers.max", maxWorkers, "tests.jvms", testsJvms); | ||
|
||
// Java properties doesn't preserve comments, so going line by line instead | ||
// The properties file isn't big, nor is the map of replacements, so not worrying about speed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also not really happy with this parsing.
My idea would be: As the template is always applied (no problem with windows or any othe roperating system), we can make the template a real template and add two search/replace markers in the file. We should then load the whole file into a String (UTF-8 encoding!!!) and then do String#replace('@PLACEHOLDER@', value)
. Those replaces can be done using replacements.entries().forEach(e -> fileContent = fileContent.replace(e.getKey(), e.getValue())
(don't use replaceAll, as it uses regex and we have no forbiddenapis here to check this!!!!).
So I would add @MAX_WORKERS@
and @TEST_JVMS@
as map keys and replace those tags. This is like Ant did it for long time :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked out and tested. Verified that props file was created. On my M1 Pro mac with 10 cores the jvms were set to 5. Looks good!
buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works as first step.
Could you make a PR for Lucene, too (please refer to discussions here).
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.lucene.gradle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just because this was based on a Lucene class doesn't mean this is a Lucene class. Should probably be packaged under o.a.solr.gradle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 -- analogous to this namespace issue. Not sure whether there are practical implications to the naming in this case, but regardless, solr package makes sense here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about it too but thought we could leave it for another day. Although it would be natural to change when we're touching this area.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only put it there because it's adjacent to the https://github.com/apache/solr/blob/1d76b053c4a6fb742a97f4250b332d755680d00e/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java that's also being used in gradlew. In actual fact, neither of them belong in buildSrc, because they aren't used by the gradle scripts themselves. I just didn't want to do something different.
I could move them both to https://github.com/apache/solr/tree/1d76b053c4a6fb742a97f4250b332d755680d00e/gradle
Either into a new directory within it, or put the WrapperDownloader in https://github.com/apache/solr/tree/1d76b053c4a6fb742a97f4250b332d755680d00e/gradle/wrapper and the new generator in https://github.com/apache/solr/tree/1d76b053c4a6fb742a97f4250b332d755680d00e/gradle/generation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the package completely. As this is a command line class only and it is not even compiled, theres no need to have a package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the reason it was originally placed there was so that it lived together with other "sources" - so that any validation checks, formatting, etc. would apply. I don't think we actually do it to buildSrc (haven't checked) but we could, in which case it'd be easier to maintain it as part of buildSrc than in some ad-hoc location.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we spin that refactoring out in a separate PR and merge this one, now that it is stable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would keep the lucene namespace as at moment this makes merging cross source trees easier (I would like to port this over to Lucene, so cherry picking this commit works from there if the path names are similar). At moment I try to port most lucene and solr gradle build imüprovements to the other project, so aligned path names makes this easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does someone want to merge it then? :)
Please add a line to |
Thanks @colvinco! |
Thanks, I created apache/lucene#12131 for Apache Lucene (cherrypicking was easy). Please have a look. |
https://issues.apache.org/jira/browse/SOLR-16641
Description
Stop generating gradle.properties and use a checked-in template instead. If
gradle.properties
isn't present when gradlew runs, it will be created from thegradle.properties.template
. The properties will be available for the first execution of gradle on a clean checkout.Also added notes on the need to have
perl
andpython3
forgradlew check
to succeed.Solution
The gradlew already had hooks that altered the arguments passed in when gradle.properties didn't exist. I've changed them to create the gradle.properties instead, and removed the
localSettings
task from gradle.Tests
Without this PR
./gradlew updateLicenses
and it will always result in a circular dependency and fail../gradlew updateLicenses
again and it will generate the gradle.properties and succeed.Checklist
Please review the following and check all that apply:
main
branch../gradlew check
.