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

Configuration cache #51

Merged
merged 17 commits into from
Dec 14, 2022
Merged

Conversation

qwert2603
Copy link
Contributor

Fixes #28 and improves test coverage.
Changes are split to commits to simplify review.

@qwert2603
Copy link
Contributor Author

@handstandsam hello! Can you review this PR please?

@handstandsam
Copy link
Collaborator

Ahh thanks, didn't see this one. Thanks for tagging, will review in the morning. Thanks!

@qwert2603
Copy link
Contributor Author

@handstandsam are there any updates on this PR?

@handstandsam
Copy link
Collaborator

I didn't forget about this, but have been busy at work and haven't gotten a chance to pull down and review it. Sorry. Still on my radar.

@handstandsam
Copy link
Collaborator

Thanks for rebasing and updating. I might defer to @autonomousapps or @joshafeinberg as I haven't implemented configuration cache myself.

@handstandsam
Copy link
Collaborator

Thanks for all this work! Because it's such a large change we'll probably have some back and forth on this one.

I know you split things up into commits, but there are 14, so it's hard even with that. If you break this apart into smaller PRs that build on each other, that may make this easier to merge in.

I added a bunch of comments, but I still will want eyes from someone who knows Configuration Cache (as I have not done any conversions).

Additionally, I want to not use Internal APIs unless it's absolutely required like it was for :buildEnvironment.

Thanks, and sorry this took me a while to get to reviewing.

@qwert2603
Copy link
Contributor Author

@handstandsam yes, I agree that large changes make some subtle bugs harder to find.
So I created PR #57 with the first part of the changes.

I added a bunch of comments,

Do you mean comments on the code? I have not seen ones..

Copy link
Collaborator

@handstandsam handstandsam left a comment

Choose a reason for hiding this comment

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

Sorry, I never submitted this. These are the comments I wrote earlier today.

Root project 'dependency-guard-root'
------------------------------------------------------------

classpath
+--- org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10
Copy link
Collaborator

Choose a reason for hiding this comment

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

What causes this change in the way baselines are made?

Copy link
Contributor Author

@qwert2603 qwert2603 Oct 13, 2022

Choose a reason for hiding this comment

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

Earlier tree baseline was equal to the output of the dependencies task, so it included some header and footer from that output. But dependencies task does not support Configuration Cache, that's why it is not used for creating tree baseline now, and AsciiDependencyReportRenderer2 is used instead.

AsciiDependencyReportRenderer2 renders only dependencies tree without header and footer, because rendering header and footer required Configuration. But Configuration can't be used as task's @get:Input and obtaining it during task's execution breaks Configuration Cache.

Comment on lines -29 to -35
public abstract class com/dropbox/gradle/plugins/dependencyguard/internal/list/DependencyGuardListTask : org/gradle/api/DefaultTask {
public fun <init> ()V
public abstract fun getAvailableConfigurations ()Lorg/gradle/api/provider/ListProperty;
public abstract fun getForRootProject ()Lorg/gradle/api/provider/Property;
public abstract fun getMonitoredConfigurations ()Lorg/gradle/api/provider/ListProperty;
public abstract fun getShouldBaseline ()Lorg/gradle/api/provider/Property;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why would this not be public anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

dependency-guard plugin is configured by DependencyGuardConfiguration and DependencyGuardPluginExtension, while DependencyGuardListTask is an implementation detail.

DependencyTreeDiffTask was also internal.

// verify tree baseline
project.assertFileExistsWithContentEqual(
filename = "lib/dependencies/compileClasspath.tree.txt",
contentFile = "simple/tree_before_update.txt",
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the rationale behind naming simple for this directory?

Copy link
Contributor Author

@qwert2603 qwert2603 Oct 13, 2022

Choose a reason for hiding this comment

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

It's named so after fixture/SimpleProject.kt.
It contains files used to verify output of baselines for SimpleProject, so it looks like an appropriate name.

// Gradle 7.4 is the minimum version for which this feature is relevant
gradleVersion = GradleVersion.version("7.4"),
args = arrayOf(":lib:dependencyGuard", "--configuration-cache")
args = arrayOf(":lib:dependencyGuard")
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think for the purposes of being explicit, --configuration-cache is still valid.

Also, by doing this, are we ending support for Gradle 7.4? At this point we've been supporting older versions. I'm open to potentially making this change, but need to discuss.

Copy link
Contributor Author

@qwert2603 qwert2603 Oct 13, 2022

Choose a reason for hiding this comment

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

--configuration-cache flag is added in fun runner in fixture/Builder, so there is no need to add it here.

I also ran tests with gradle-7.4.2 -- they all passed successfully (#58).

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest writing parameterized tests so you can test against various Gradle versions, if you want to ensure support for older versions as well as newer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created #62

@@ -4,12 +4,17 @@ import com.dropbox.gradle.plugins.dependencyguard.util.createDirectories
import com.dropbox.gradle.plugins.dependencyguard.util.writeText
import java.nio.file.Path

class SimpleProject : AbstractProject() {
class SimpleProject(
private val tree: Boolean = true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you make this be a parameter without a default value? I feel like the tests would be more explicit that way.

} else {
DependencyTreeDiffTask::class.java
}
val taskClass = DependencyTreeDiffTask::class.java
Copy link
Collaborator

Choose a reason for hiding this comment

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

🤔 - will have to see later on in this PR how you support the Build Environment tree for ./gradlew :buildEnvironment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The tree baseline for the root project is created from classpath configuration as before.
Now the tree baseline is created in a general way (via ResolvedComponentResult) for the root project and for the usual gradle module.

Comment on lines +4 to +11
import org.gradle.api.tasks.diagnostics.internal.TextReportRenderer
import org.gradle.api.tasks.diagnostics.internal.dependencies.AsciiDependencyReportRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.DependencyGraphsRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.NodeRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.SimpleNodeRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableModuleResult
import org.gradle.internal.graph.GraphRenderer
import org.gradle.internal.logging.text.StyledTextOutput
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would like to stay away from internal Gradle APIs as much as possible. I had to do it for the buildEnvironment tree only #25, but I want to stay away from internal APIs if there is anything public available. That will ensure better version compatibility in the future.

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 agree that it's better to avoid internal api usage, but dependencies task does not support Configuration Cache. That's why AsciiDependencyReportRenderer2 was added to render ResolvedComponentResult.

I didn't find another way to render dependencies tree, so I needed to stay on internal api. But I'm ready to switch to public api that I'm not aware of, if it makes the same thing.

Copy link
Contributor

Choose a reason for hiding this comment

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

What does this class do? Could you reimplement it? Or even just copy and paste the code into this project?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

class AsciiDependencyReportRenderer2 renders dependencies tree of the particular configuration (represented by org.gradle.api.artifacts.result.ResolvedComponentResult).

This is a modified copy of AsciiDependencyReportRenderer from Gradle sources.

AsciiDependencyReportRenderer works with org.gradle.api.artifacts.Configuration, while AsciiDependencyReportRenderer2 works with org.gradle.api.artifacts.result.ResolvedComponentResult. This is because org.gradle.api.artifacts.Configuration is not available in task's actions, when configuration cache is enabled.

Actually, original AsciiDependencyReportRenderer in public void render(Configuration configuration) receives ResolvedComponentResult from org.gradle.api.artifacts.Configuration, so there is not much changes in AsciiDependencyReportRenderer2.

Another change is that AsciiDependencyReportRenderer2 renders only dependencies tree without header and footer, because rendering header and footer requeires org.gradle.api.artifacts.Configuration in original AsciiDependencyReportRenderer. But that is not that important, because we are more interested in dependencies trees diff, that in header and footer.

/**
* Simplified version of [AsciiDependencyReportRenderer] that renders [ResolvedComponentResult].
*/
internal class AsciiDependencyReportRenderer2 : TextReportRenderer() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have seen these internal APIs, but haven't used it. Can the comment declare if this is used for just Trees, and if it's used for :buildEnvironment or normal :dependencies tasks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

DependencyTreeDiffTask is not based on :buildEnvironment or :dependencies now.
It is a simple task that receives ResolvedComponentResult as input and renders its dependencies tree to file using AsciiDependencyReportRenderer2.

@@ -21,6 +21,7 @@ dependencyGuard {
// All dependencies included in Production Release APK
configuration("releaseRuntimeClasspath") {
modules = true
tree = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd like to discourage the use of tree format as I feel like it's more helpful in local debugging. It's nice to have it there, but I didn't use it in the sample because 1) it's not as useful in most situations as it's so noisy 2) the build environment piece used internal APIs, so it's more of a "use at your own risk".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, tree format is actually not that useful, so I'll revert this change.

@qwert2603 qwert2603 removed the request for review from joshafeinberg October 13, 2022 13:36
@qwert2603
Copy link
Contributor Author

Arghh, the request for review from joshafeinberg was removed when requesting a review from handstandsam

@qwert2603
Copy link
Contributor Author

@handstandsam Hi! Are there any updates on this PR?

@handstandsam
Copy link
Collaborator

@qwert2603 - Sorry, dependency-guard has been working for our use cases so I haven't had any extra time to look into this. Configuration Cache is important, but the workaround ensures that configuration cache is aware of it must running. Therefore it is working, but not with config cache.

In order to feel comfortable merging, I would want to sit down and run the new code as it's not small changes.

I sent you a DM on Kotlin Lang Slack about this topic if you can check and reply there. Thank you!

@@ -5,5 +5,4 @@ import org.gradle.util.GradleVersion
internal object GradleVersion {
private val current = GradleVersion.current()
val isAtLeast73 = current >= GradleVersion.version("7.3")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we drop this as well now?

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 think it may be dropped together will adding parameterized tests (#62)

@handstandsam handstandsam merged commit 6be98d6 into dropbox:main Dec 14, 2022
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.

Leverage Gradle 7.5's "Dependency Resolution Results" to enable Configuration Cache
3 participants