Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Avoid creating and configuring tasks when unnecessary #394

Closed
wants to merge 16 commits into from

Conversation

chanseokoh
Copy link
Contributor

@chanseokoh
Copy link
Contributor Author

However, this still doesn't work because project.afterEvaluate() is forbidden in the new configuration avoidance API. From https://docs.gradle.org/current/userguide/task_configuration_avoidance.html, it says

  1. Some APIs may be disallowed if you try to access them from the new API’s configuration blocks. For example, Project.afterEvaluate() cannot be called when configuring a task registered with the new API.

So when actually applied to a project, it fails:

* What went wrong:
A problem occurred configuring project ':backend'.
> Failed to notify project evaluation listener.
   > Could not create task ':backend:downloadCloudSdk'.
      > Project#afterEvaluate(Action) on project ':backend' cannot be executed in the current context.
   > Could not create task ':backend:appengineDeployAll'.
      > Project#afterEvaluate(Action) on project ':backend' cannot be executed in the current context.

@codecov
Copy link

codecov bot commented Feb 10, 2021

Codecov Report

Merging #394 (bae6dc2) into master (093c818) will decrease coverage by 2.61%.
The diff coverage is 88.34%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     GoogleCloudPlatform/app-gradle-plugin#394      +/-   ##
============================================
- Coverage     75.76%   73.14%   -2.62%     
+ Complexity      277      275       -2     
============================================
  Files            42       43       +1     
  Lines          1073     1013      -60     
  Branches         41       42       +1     
============================================
- Hits            813      741      -72     
- Misses          242      255      +13     
+ Partials         18       17       -1     
Impacted Files Coverage Δ Complexity Δ
...tools/gradle/appengine/core/CloudSdkLoginTask.java 60.00% <ø> (ø) 2.00 <0.00> (ø)
...ools/gradle/appengine/standard/ExplodeWarTask.java 100.00% <ø> (ø) 5.00 <0.00> (ø)
.../cloud/tools/gradle/appengine/core/DeployTask.java 53.84% <33.33%> (-9.80%) 4.00 <1.00> (ø)
...e/appengine/sourcecontext/SourceContextPlugin.java 84.09% <76.19%> (-5.10%) 9.00 <5.00> (ø)
...pengine/core/AppEngineCorePluginConfiguration.java 79.71% <77.63%> (-6.01%) 37.00 <29.00> (-7.00)
.../cloud/tools/gradle/appengine/AppEnginePlugin.java 84.21% <100.00%> (ø) 8.00 <1.00> (ø)
...adle/appengine/appyaml/AppEngineAppYamlPlugin.java 90.76% <100.00%> (+0.29%) 14.00 <12.00> (+5.00)
...ud/tools/gradle/appengine/core/BaseDeployTask.java 100.00% <100.00%> (ø) 1.00 <1.00> (?)
...oud/tools/gradle/appengine/core/DeployAllTask.java 91.66% <100.00%> (ø) 8.00 <1.00> (ø)
...ud/tools/gradle/appengine/core/DeployCronTask.java 55.55% <100.00%> (ø) 3.00 <1.00> (ø)
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 093c818...bae6dc2. Read the comment docs.

@chanseokoh
Copy link
Contributor Author

chanseokoh commented Feb 10, 2021

Fixed the problem, and the integration tests are passing. However, I don't have strong confidence that it doesn't break anything. Previously, even after the integration tests passing, I encountered an error on a sample project. For now, I'll leave this in the draft state.

@@ -89,10 +91,10 @@ private void configureExtensions() {
// we can only set the default location of "archive" after project evaluation (callback)
if (stageExtension.getArtifact() == null) {
if (project.getPlugins().hasPlugin(WarPlugin.class)) {
War war = (War) project.getProperties().get("war");
War war = tasks.withType(War.class).getByName("war");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason that I don't know, the previous code was returning null.

Also I think the new code may still unnecessarily instantiate the war task.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right you are. It does instantiate create task.
The way to avoid task creation is stageExtension.setArtifact(tasks.named<War>(WarPlugin.WAR_TASK_NAME).map { it.getArchiveFile() })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed getByName() in another place in bae6dc2. I assume getProject().zipTree(object) will work fine when given a TaskProvider. (Previously, it was getting File directly from getArchivePath().) Does this look good?

@chanseokoh chanseokoh marked this pull request as ready for review February 12, 2021 22:59
Comment on lines 268 to 271
if (injectDeployExtension) {
project.afterEvaluate(
project -> taskProvider.configure(task -> task.setDeployExtension(deployExtension)));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of afterEvaluate here?
It looks like task.setDeployExtension(deployExtension) can be called during task registration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same question. (I have never worked on this repo, and I don't have a lot of Gradle knowledge.)

What I can see is that deployExtension is instantiated in the following way in Plugin.apply().

First, a parent extension is created with .create()

    appengineExtension =
        project.getExtensions().create("appengine", AppEngineAppYamlExtension.class);

and then the sub-extension (this below is appengineExtension created above)

    deploy =
        ((ExtensionAware) this).getExtensions().create(DEPLOY_EXT, DeployExtension.class, project);

This deploy is what is called deployExtension in this class (if I am following the code flow correctly).

So the question is, do we still need to use afterEvaluate() when calling setDeployExtension(deployExtension)? I guess not, because it's just passing and setting a Java reference. But since I have never worked on this repo, I'm concerned there may be something that I'm not seeing. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess not, because it's just passing and setting a Java reference

Indeed. If the reference is not changed, then it can be passed without afterEvaluate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed more afterEvaluate blocks in 1ca1a13 and 29190de.

stageExtension.setArtifact(war.getArchivePath());
} else if (project.getPlugins().hasPlugin(JavaPlugin.class)) {
Jar jar = (Jar) project.getProperties().get("jar");
Jar jar = tasks.withType(Jar.class).getByName("jar");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: it is better to use tasks.named(...)

Comment on lines +116 to +117
task.setStageDirectory(stageExtension.getStagingDirectory());
task.setDeployExtension(deploy);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use Property<...> for stageExtension.getStagingDirectory, then you could move this task configuration outside of afterEvaluate.

Comment on lines 141 to 142
project.afterEvaluate(
project -> stage.configure(task -> task.setStagingConfig(stageExtension)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is afterEvaluate needed here?

@InLaw
Copy link

InLaw commented Jul 20, 2021

What can be done to continue here, who needs to do the review?

Jar jar = (Jar) project.getProperties().get("jar");
stageExtension.setArtifact(jar.getArchivePath());
stageExtension.setArtifact(
tasks.withType(Jar.class).named("jar").map(jar -> jar.getArchivePath()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to create a filtered task collection:

Suggested change
tasks.withType(Jar.class).named("jar").map(jar -> jar.getArchivePath()));
tasks.named("jar", Jar.class).map(jar -> jar.getArchivePath()));

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

Successfully merging this pull request may close these issues.

app-gradle-plugin breaks tasks in multi project build?
5 participants