-
Notifications
You must be signed in to change notification settings - Fork 83
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
basic Gradle integration test scaffolding #789
Conversation
4632e6f
to
8584e97
Compare
8584e97
to
095e67a
Compare
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.
Partial review
import org.gradle.language.base.plugins.LifecycleBasePlugin | ||
import org.gradle.plugins.ide.idea.model.IdeaModel | ||
|
||
abstract class IntegrationTestsConventionPlugin : Plugin<Project> { |
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 you add a doc comment for this?
Also is there a more specific name that works here? Right now it's a bit confusing having an integrationTest
task and the integration-tests
module that are both unrelated to each other. Maybe this could be pluginIntegrationTest
, gradleIntegrationTest
, etc for the task name to differentiate it?
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!
when (target.path) { | ||
":annotations", | ||
":annotations-optional", | ||
":compiler", | ||
":compiler-api", | ||
":compiler-utils", | ||
":gradle-plugin", | ||
-> target.setBuildDir() |
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.
Conditionally applying by target path/module like this feels unexpected instead of setting the build dir for anyone that has chosen to apply this plugin. What do you think about having a separate plugin to handle the case for simple lib modules that only want the above (kotlin-jvm, ktlint) plugins applied? The simpler plugin could be something like MinimalLibraryPlugin
or the other direction where the library plugin with this build dir setup logic could be named around what it's doing differently to indicate which modules should use it.
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!
|
||
internal fun Project.isInMainAnvilBuild() = rootProject.name == "anvil" | ||
|
||
internal fun Project.isInDelegateBuild() = rootProject.name == "delegate" |
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 you add some high level documentation somewhere around the main build vs delegate build, why we have both, etc?
65704b8
to
078e8ea
Compare
build-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/BasePlugin.kt
Outdated
Show resolved
Hide resolved
...d-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/KtlintConventionPlugin.kt
Outdated
Show resolved
Hide resolved
...-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/PublishConventionPlugin.kt
Show resolved
Hide resolved
...-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/PublishConventionPlugin.kt
Show resolved
Hide resolved
target.extras["skipDokka"] = true | ||
} | ||
|
||
target.rootProject.tasks.named("publishToBuildM2").dependsOn(publishToBuildM2) |
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.
Am I reading correctly that this is making sure when we run publish at the root level, that all subprojects applying the plugin get their publish task executed?
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.
Yep. The publish tasks don't chain together the way that build tasks do, so this is a pretty common catch-all.
build-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/BasePlugin.kt
Show resolved
Hide resolved
build-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/CompositePlugin.kt
Show resolved
Hide resolved
override fun beforeApply(target: Project) { | ||
target.plugins.apply(target.libs.plugins.kotlin.jvm.pluginId) | ||
|
||
target.plugins.apply(PublishConventionPlugin::class.java) |
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 keep publishing separate and have libs apply it as needed? Not every library necessarily needs to be published, unless we expect non-published library modules to use a different plugin
For example, the use-case I'm thinking of is that we create a new module like compiler-utils-2
that is only used internally by compiler-utils
and does not need to be exposed to anyone else.
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!
|
||
target.logVersionInfo() | ||
|
||
if (target.isInMainAnvilBuild() || target.isInDelegateBuild()) { |
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.
What are the other options beyond main build and delegate build 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.
Once upon a time...
I forgot to clean this up. :)
build-logic/settings/src/main/kotlin/com/squareup/anvil/builds/settings/SettingsPlugin.kt
Show resolved
Hide resolved
91fae50
to
c6b71f3
Compare
c6b71f3
to
f28bd56
Compare
...logic/conventions/src/main/kotlin/com/squareup/anvil/benchmark/CreateBenchmarkProjectTask.kt
Show resolved
Hide resolved
build-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/CompositePlugin.kt
Show resolved
Hide resolved
val newRequests = oldRequests.map { request -> | ||
|
||
val originalSplit = request.args.splitTaskArgs() | ||
|
||
val taskPaths = originalSplit.mapTo(mutableSetOf()) { it.first() } | ||
|
||
val includedProjects = gradle.includedBuilds | ||
.asSequence() | ||
.filterIsInstance<IncludedBuildImpl>() | ||
.flatMap { impl -> | ||
|
||
val defaultIncludedBuild = impl.target as DefaultIncludedBuild | ||
|
||
defaultIncludedBuild.mutableModel.projectRegistry.allProjects | ||
} | ||
|
||
val newSplit = originalSplit.flatMap { taskWithArgs -> | ||
|
||
val taskName = taskWithArgs.first() | ||
|
||
if (taskName.startsWith(':')) { | ||
// qualified task names aren't propagated to included builds | ||
return@flatMap listOf(taskWithArgs) | ||
} | ||
|
||
// Don't propagate help tasks | ||
if (taskName == "help") return@flatMap listOf(taskWithArgs) | ||
|
||
val included = includedProjects.mapNotNull { includedProject -> | ||
|
||
val includedPath = "${includedProject.identityPath}:$taskName" | ||
|
||
// Don't include tasks that are already in the task graph | ||
if (taskPaths.contains(includedPath)) return@mapNotNull null | ||
|
||
includedProject.tasks.namedOrNull(taskName) ?: return@mapNotNull null | ||
|
||
target.logger.quiet("The task $taskName will delegate to $includedPath") | ||
|
||
buildList<String> { | ||
add(includedPath) | ||
addAll(taskWithArgs.subList(1, taskWithArgs.size)) | ||
} | ||
} | ||
|
||
buildList { | ||
|
||
// Looks to see if any project in this build has a task with this name. | ||
val resolvedInRootBuild = target.allprojects |
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.
Could you add some tests around some of this task finagling logic? Could be a follow-up PR in the interest of not further delaying the rest of the changes
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.
Will do.
...-logic/conventions/src/main/kotlin/com/squareup/anvil/conventions/PublishConventionPlugin.kt
Show resolved
Hide resolved
private fun configureTests(target: Project) { | ||
target.tasks.withType(Test::class.java).configureEach { task -> | ||
|
||
task.maxParallelForks = Runtime.getRuntime().availableProcessors() |
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.
It looks like previously we only did this for local machines. Is there any downside to now setting it on CI?
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.
Nope. It's a pretty common setting.
task.maxParallelForks = Runtime.getRuntime().availableProcessors() | ||
|
||
task.testLogging { logging -> | ||
logging.events("passed", "skipped", "failed") |
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.
Why do we not include the 'standardOut', 'standardError'
events 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.
Anything that we actually need to see (for a failed test) will still be included in the output as the exception/stacktrace. There's so much noise in the console output that it becomes difficult to find an actual error when you need to.
No description provided.