Skip to content
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

Avoid calling afterEvaluate on already evaluated project #210

Merged

Conversation

chali
Copy link
Collaborator

@chali chali commented Mar 30, 2021

This should help with #206

@chali chali requested review from boris-petrov and f4lco March 30, 2021 00:57
@boris-petrov
Copy link
Member

The tests do pass here and the deprecation warning is gone... but does it still do the same thing? Now afterProjectEvaluate is not called on every project but rather only on the root plugin one. Is that OK? Otherwise the change with rootProject.getGradle().projectsEvaluated looks great, good catch @chali!

@f4lco
Copy link
Collaborator

f4lco commented Mar 30, 2021

Now afterProjectEvaluate is not called on every project but rather only on the root plugin one. Is that OK?

I suppose. I have theories (we might dig deeper and debug if you doubt):

  • Suppose there are multiple Gretty plugin applications within the multi-project build. I guess in the former behavior afterProjectEvaluate was likely to be called too often: if every Gretty plugin application registers the callback for every other project, that registers the callback more than once per project. This code would be run more than once:
    for(def p in rootProject.allprojects)
    p.afterEvaluate { proj ->
    afterProjectEvaluate(proj)

    I'd assume this behavior is now better: for every Gretty plugin application, we call afterProjectEvaluate only once with the current project, and thus set up tasks and dependencies only once.
  • That leaves only one case unsupported: doing something for projects with a Gretty extension, but no plugin application. Check the guard clause on afterProjectEvaluate:
    private void afterProjectEvaluate(Project project) {
    if(project.extensions.findByName('gretty')) {
    addConfigurationsAfterEvaluate(project)

    In the former behavior, if someone managed to create a Gretty extension without a Gretty plugin application, we would call afterProjectEvaluate on it, because of the "on plugin application, register callback for all projects with a Gretty extension" logic. In the new behavior, we only find and configure projects that have both, a Gretty plugin application, and a Gretty extension. This is reasonable in my opinion.

Thanks  @chali for your contribution 💯

@f4lco f4lco self-requested a review March 30, 2021 08:32
@chali
Copy link
Collaborator Author

chali commented Mar 30, 2021

Here is my understanding which mostly overlaps with @f4lco.

The previous part would register afterProjectEvaluate(proj) for every module (including the root).

for(def p in rootProject.allprojects)
p.afterEvaluate { proj ->
afterProjectEvaluate(proj)

The purpose of gretty_ in ext is to register callbacks only once. It is because registration is happening in every submodule which does apply plugin: 'gretty' I definitely agree that this technique is far from ideal. However, I had no better idea. I was thinking about BuildService for that. It is a native Gradle construct for things that should be only once per build. I would be cautious with memoize. Those things get tricky with build parallelization and caching. If there are tests covering those use cases to give us confidence about the change I would say it definitely looks better than the current ext property check.

As @f4lco pointed out there is this condition inside afterProjectEvaluate.

private void afterProjectEvaluate(Project project) {
if(project.extensions.findByName('gretty')) {
addConfigurationsAfterEvaluate(project)

It means we would register afterProjectEvaluate for every single module but then only those that have gretty extension will make any meaningful work. And those who have gretty extension actually apply the whole plugin which does this registration in the first place.

I made an assumption that plugin and extension are always applied created together. If that is not true the change would miss projects with only gretty extension but not the plugin.

@f4lco
Copy link
Collaborator

f4lco commented Mar 30, 2021

I would be cautious with memoize. Those things get tricky with build parallelization and caching.

Yes. I was having second thoughts about memoize, too. I just wanted a better solution so badly ☹️ Anyway, then it's good to go as-is. It's better than before. There's now a comment in it explaining the situation. Thanks for that.

Yeah, that's some overlap in understanding right there 😄 From my perspective there's nothing new / nothing to correct. It's nice to learn about BuildService, though. Thanks for digging it up. I believe BuildService is a bit of an overkill for this problem.

I made an assumption that plugin and extension are always applied created together. If that is not true the change would miss projects with only gretty extension but not the plugin.

I think that's a merely theoretical situation. I would recommend to every build author to create extensions and apply the plugin together. I just wanted to show every possible aspect of the change, so please don't worry about it too much.

@boris-petrov
Copy link
Member

@f4lco - go ahead and merge when you're fine. :)

@f4lco f4lco merged commit ac98e45 into gretty-gradle-plugin:master Mar 31, 2021
@f4lco
Copy link
Collaborator

f4lco commented Mar 31, 2021

@boris-petrov will you take care of cherry-picking both #210 and #207 to 3.x? You wanted to wait for a new 3.x release and I don't know the exact status of that.

@boris-petrov
Copy link
Member

I will do the cherry-picking, yes. As for 3.0.4 - it has been out since yesterday so be sure to go and update! 😄

@chali
Copy link
Collaborator Author

chali commented Mar 31, 2021

@boris-petrov do you have any estimates when this change could be included and released in 3.x?

@boris-petrov
Copy link
Member

@chali - unfortunately not for now. We have to check how publishing to Maven Central works (I believe @javabrett has already "applied" there) and then it's going to be easier. As soon as possible I hope. :)

Does this stop you from using Gretty in any way? Perhaps with Gradle 7?

@chali
Copy link
Collaborator Author

chali commented Apr 1, 2021

@boris-petrov We have about 25 projects affected by this issue if they switch to Gradle 7. However I still have a ton of compatibility work ahead of me so it will take a while before we will be able to switch to Gradle 7. I'm confident that it won't be an issue to have fix released later. I'm assuming based on your answer that it might happen in following days or weeks not months? :-)

@boris-petrov
Copy link
Member

Hopefully! :)

@ismart-dev
Copy link

We are trying to move to Gradle7 and are hitting this problem with Gretty. Is there a temporary workaround? Or is there a way to get a 3.x snapshot build with the fix?

@boris-petrov
Copy link
Member

@ismart-dev - can you try this way of using a Gretty snapshot? Be sure to use the latest commit from gretty-3.x - 10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.

@ismart-dev
Copy link

@boris-petrov - Thanks for the pointer. Unfortunately, it doesn't work. My build fails with:

`FAILURE: Build failed with an exception.

  • What went wrong:
    A problem occurred configuring project ':tn-app'.

Could not resolve all artifacts for configuration ':tn-app:classpath'.
Could not find com.github.gretty-gradle-plugin:gretty:10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.
Searched in the following locations:
- file:/Users/ismart-dev/work/m2/repository/com/github/gretty-gradle-plugin/gretty/10d53b5a331a7aac0b27778a2a4b8ab9c9094a10/gretty-10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.pom
- https://repo1.maven.org/maven2/com/github/gretty-gradle-plugin/gretty/10d53b5a331a7aac0b27778a2a4b8ab9c9094a10/gretty-10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.pom
- https://repo.maven.apache.org/maven2/com/github/gretty-gradle-plugin/gretty/10d53b5a331a7aac0b27778a2a4b8ab9c9094a10/gretty-10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.pom
- https://jitpack.io/com/github/gretty-gradle-plugin/gretty/10d53b5a331a7aac0b27778a2a4b8ab9c9094a10/gretty-10d53b5a331a7aac0b27778a2a4b8ab9c9094a10.pom
Required by:
project :tn-app
`

Looking at the build log here: https://jitpack.io/com/github/gretty-gradle-plugin/gretty/10d53b5a331a7aac0b27778a2a4b8ab9c9094a10/build.log

The gretty plugin build fails with:

`> Task :cleanIntegrationTests FAILED

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.

  • What went wrong:
    Execution failed for task ':libs:gretty-spock:compileGroovy'.

java.lang.ExceptionInInitializerError (no error message)

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    ==============================================================================

2: Task failed with an exception.

  • What went wrong:
    Execution failed for task ':integrationTests:buildSrc:gretty-integrationTest:compileGroovy'.

Could not resolve all files for configuration ':integrationTests:buildSrc:gretty-integrationTest:compileClasspath'.
Could not find org.gretty:gretty:3.0.5-SNAPSHOT.
Searched in the following locations:
- file:/home/jitpack/build/build/privateRepo/org/gretty/gretty/3.0.5-SNAPSHOT/maven-metadata.xml
- file:/home/jitpack/build/build/privateRepo/org/gretty/gretty/3.0.5-SNAPSHOT/gretty-3.0.5-SNAPSHOT.pom
- https://repo.maven.apache.org/maven2/org/gretty/gretty/3.0.5-SNAPSHOT/maven-metadata.xml
- https://repo.maven.apache.org/maven2/org/gretty/gretty/3.0.5-SNAPSHOT/gretty-3.0.5-SNAPSHOT.pom
Required by:
project :integrationTests:buildSrc:gretty-integrationTest
`

Any help much appreciated...

@boris-petrov
Copy link
Member

@ismart-dev - right. I opened a new issue for this, please subscribe for it to get a notification when it's resolved.

@boris-petrov
Copy link
Member

@ismart-dev, @chali - do you mind trying a snapshot version from JitPack? I believe it should contain all the fixes and should work on Gradle 7 and multi-module projects.

@chali
Copy link
Collaborator Author

chali commented Jun 10, 2021

hey @boris-petrov sorry for the late reply. I finally got a chance to try it out but I'm running into some issues while using Jitpack.

I declared my dependency this way:

buildscript {
    dependencies {
        classpath 'com.github.gretty-gradle-plugin:gretty:gretty-3.x-SNAPSHOT'
    }
    repositories {
		maven { url 'https://jitpack.io' }
	}
}

I'm getting this error when resolving the plugin:

* What went wrong:
A problem occurred configuring project ':mapclientapp'.
> Could not resolve all artifacts for configuration ':mapclientapp:classpath'.
   > Could not find com.github.gretty-gradle-plugin.gretty:gretty-filter:gretty-3.x-SNAPSHOT.
     Searched in the following locations:
       - https://jitpack.io/com/github/gretty-gradle-plugin/gretty/gretty-filter/gretty-3.x-SNAPSHOT/maven-metadata.xml
       - https://jitpack.io/com/github/gretty-gradle-plugin/gretty/gretty-filter/gretty-3.x-SNAPSHOT/gretty-filter-gretty-3.x-v3.0.4-g749988a-43.pom
     Required by:
         project :aproject > com.github.gretty-gradle-plugin:gretty:gretty-3.x-SNAPSHOT:v3.0.4-g749988a-43

The list is longer, having multiple gretty submodules there.
Am I missing anything in the declaration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants