Skip to content

Commit

Permalink
Add support for isolated projects
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbonnin committed Jan 13, 2025
1 parent 16dc61c commit d3f6059
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 32 deletions.
7 changes: 1 addition & 6 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,11 @@ POM_DEVELOPER_NAME=Apollo

android.useAndroidX=true

# Keep in sync with other projects
# Give more memory to the Gradle daemon
org.gradle.jvmargs=-Xmx8g
# Do not automatically add stdlib dependency
kotlin.stdlib.default.dependency=false
# Enable the build cache
org.gradle.caching=true
# Enable the configuration cache
org.gradle.configuration-cache=true

#org.gradle.unsafe.isolated-projects=true
org.gradle.parallel=true

org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,15 @@ abstract class DefaultApolloExtension(
null -> { // default: automatic detection
project.configurations.configureEach {
it.dependencies.configureEach {
// Try to detect if a native version of apollo-normalized-cache-sqlite is in the classpath
if (it.group?.contains("apollo") == true
/*
* Try to detect if a native version of apollo-normalized-cache-sqlite is in the classpath
* This is a heuristic and will not work in 100% of the cases.
*
* Note: we only check external dependencies as reading the group of project dependencies
* is not compatible with isolated projects
*/
if (it is ExternalModuleDependency
&& it.group?.contains("apollo") == true
&& it.name.contains("normalized-cache-sqlite")
&& !it.name.contains("jvm")
&& !it.name.contains("android")) {
Expand Down Expand Up @@ -360,10 +367,8 @@ abstract class DefaultApolloExtension(

it.inputs.property("allVersions", Callable {
val allDeps = (
getDeps(project.rootProject.buildscript.configurations) +
getDeps(project.buildscript.configurations) +
getDeps(project.configurations)

)
allDeps.distinct().sorted()
})
Expand Down Expand Up @@ -1033,12 +1038,16 @@ abstract class DefaultApolloExtension(
.filter {
/**
* When using plugins {}, the group is the plugin id, not the maven group
*/
/**
*
* the "_" check is for refreshVersions,
* see https://github.com/jmfayard/refreshVersions/issues/507
*
* Note: we only check external dependencies as reading the group of project dependencies
* is not compatible with isolated projects
*
*/
it.group in listOf("com.apollographql.apollo", "com.apollographql.apollo.external")
it is ExternalModuleDependency
&& it.group in listOf("com.apollographql.apollo", "com.apollographql.apollo.external")
&& it.version != "_"
}.mapNotNull { dependency ->
dependency.version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ fun Project.apolloGetKotlinPluginVersion(): String? {
return project.getKotlinPluginVersion()
}

/*
* Inspired by SQLDelight:
* https://github.com/sqldelight/sqldelight/blob/ae8c348f6cf76822828bc65832106ec151ca5b6c/sqldelight-gradle-plugin/src/main/kotlin/app/cash/sqldelight/gradle/kotlin/LinkSqlite.kt#L7
* https://github.com/sqldelight/sqldelight/issues/1442
*
* Ideally this can be forwarded automatically, but I don't think this can be done as of today.
*/
internal fun linkSqlite(project: Project) {
val extension = project.kotlinMultiplatformExtension ?: return

Expand Down
7 changes: 5 additions & 2 deletions libraries/apollo-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ tasks.register("cleanStaleTestProjects") {
}
}

tasks.withType<Test> {
tasks.register("publishDependencies") {
dependsOn("publishAllPublicationsToPluginTestRepository")
dependsOn(":apollo-annotations:publishAllPublicationsToPluginTestRepository")
dependsOn(":apollo-api:publishAllPublicationsToPluginTestRepository")
dependsOn(":apollo-ast:publishAllPublicationsToPluginTestRepository")
Expand All @@ -143,8 +144,10 @@ tasks.withType<Test> {
dependsOn(":apollo-compiler:publishAllPublicationsToPluginTestRepository")
dependsOn(":apollo-gradle-plugin-external:publishAllPublicationsToPluginTestRepository")
dependsOn(":apollo-tooling:publishAllPublicationsToPluginTestRepository")
dependsOn("publishAllPublicationsToPluginTestRepository")
}

tasks.withType<Test> {
dependsOn("publishDependencies")
dependsOn("cleanStaleTestProjects")

addRelativeInput("testFiles", "testFiles")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class GradleToolingTests {

@Test
fun `tooling model exposes apollo metadata dependencies`() {
TestUtils.withTestProject("multi-modules-diamond") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-diamond") { dir ->

val toolingModel = GradleConnector.newConnector()
.forProjectDirectory(File(dir, "leaf"))
.connect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import util.TestUtils
import com.google.common.truth.Truth
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Test
import util.disableIsolatedProjects
import java.io.File

class KotlinPluginVersionTests {
Expand All @@ -14,6 +15,8 @@ class KotlinPluginVersionTests {
@Test
fun `kotlin JVM min version succeeds`() {
TestUtils.withTestProject("kotlin-plugin-version-min") { dir ->
dir.disableIsolatedProjects() // old KGP versions do not support isolated projects

val result = TestUtils.executeTask("build", dir)

Truth.assertThat(result.task(":build")!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import org.gradle.testkit.runner.UnexpectedBuildFailure
import org.junit.Assert
import org.junit.Test
import util.TestUtils
import util.disableIsolatedProjects
import java.io.File

class LanguageVersionTests {
@Test
fun `compiling with 1_5 features with Kotlin 1_5 is working`() {
withProject(kotlinLanguageVersion = "1.5", apolloLanguageVersion = "1.5") { dir ->
dir.disableIsolatedProjects() // old KGP versions do not support isolated projects
TestUtils.executeTaskAndAssertSuccess(":assemble", dir)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,21 @@ apollo {

val apolloConfiguration = """
abstract class InstallGraphQLFilesTask: DefaultTask() {
@get:InputDirectory
abstract val inputDir: DirectoryProperty
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
@TaskAction
fun taskAction() {
println("installing graphql files")
project.file( "src/main/graphql/com/example").copyRecursively(outputDir.asFile.get())
inputDir.asFile.get().copyRecursively(outputDir.asFile.get())
}
}
val installTask = tasks.register("installTask", InstallGraphQLFilesTask::class.java) {
outputDir.set(project.file("build/toto"))
inputDir.set(project.file("src/main/graphql/com/example"))
}
apollo {
service("service") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,35 @@ import org.gradle.testkit.runner.UnexpectedBuildFailure
import org.junit.Assert
import org.junit.Test
import util.TestUtils
import util.disableIsolatedProjects
import util.replaceInText
import java.io.File


internal fun testProjectWithIsolatedProjectsWorkaround(name: String, block: (File) -> Unit) {
/*
* There seems to be an issue running KGP in project isolation mode
* It's happening mostly for multi-module tests, I'm guessing because of a race or so.
* See https://youtrack.jetbrains.com/issue/KT-74394
*/
TestUtils.withTestProject(name) { dir ->
dir.disableIsolatedProjects()
block(dir)
}
}

class MultiModulesTests {
@Test
fun `multi-modules project compiles`() {
TestUtils.withTestProject("multi-modules") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules") { dir ->
val result = TestUtils.executeTask(":leaf:assemble", dir)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":leaf:assemble")!!.outcome)
}
}

@Test
fun `multi-modules project can use transitive dependencies`() {
TestUtils.withTestProject("multi-modules-transitive") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-transitive") { dir ->
val result = TestUtils.executeTask(":leaf:assemble", dir)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":leaf:assemble")!!.outcome)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":leaf:generateServiceApolloSources")!!.outcome)
Expand All @@ -32,15 +46,15 @@ class MultiModulesTests {
/**
* A diamond shaped hierarchy does not include the schema multiple times
*/
TestUtils.withTestProject("multi-modules-diamond") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-diamond") { dir ->
val result = TestUtils.executeTask(":leaf:jar", dir)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":leaf:generateServiceApolloSources")!!.outcome)
}
}

@Test
fun `duplicate fragments are detected correctly`() {
TestUtils.withTestProject("multi-modules-duplicates") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-duplicates") { dir ->
// duplicate fragments in sibling modules are fine
TestUtils.executeTaskAndAssertSuccess(":node1:impl:generateApolloSources", dir)

Expand All @@ -63,7 +77,7 @@ class MultiModulesTests {

@Test
fun `changing a fragment in module does not recompile siblings`() {
TestUtils.withTestProject("multi-modules-duplicates") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-duplicates") { dir ->
// Change the fragment so that it doesn't name clash anymore
File(dir, "node1/impl/src/main/graphql/com/library/operations.graphql").replaceInText("CatFragment", "CatFragment1")
// Execute jar a first time
Expand All @@ -89,7 +103,7 @@ class MultiModulesTests {

@Test
fun `custom scalars are registered if added to customScalarMappings`() {
TestUtils.withTestProject("multi-modules-custom-scalar") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-custom-scalar") { dir ->
TestUtils.executeTaskAndAssertSuccess(":leaf:assemble", dir)
// Date and GeoPoint is generated in the root module
Assert.assertTrue(File(dir, "root/build/generated/source/apollo/service/com/library/type/Date.kt").exists())
Expand All @@ -101,7 +115,7 @@ class MultiModulesTests {

@Test
fun `scalar mapping can only be registered in the schema module`() {
TestUtils.withTestProject("multi-modules-custom-scalar-defined-in-leaf") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-custom-scalar-defined-in-leaf") { dir ->
try {
TestUtils.executeTaskAndAssertSuccess(":leaf:assemble", dir)
Assert.fail("the build did not detect scalar mapping registered in leaf module")
Expand All @@ -113,15 +127,15 @@ class MultiModulesTests {

@Test
fun `metadata is published`() {
TestUtils.withTestProject("multi-modules-publishing-producer") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-publishing-producer") { dir ->
val result = TestUtils.executeTask(
"publishAllPublicationsToPluginTestRepository",
dir
)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":schema:publishAllPublicationsToPluginTestRepository")?.outcome)
Assert.assertEquals(TaskOutcome.SUCCESS, result.task(":fragments:publishAllPublicationsToPluginTestRepository")?.outcome)
}
TestUtils.withTestProject("multi-modules-publishing-consumer") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-publishing-consumer") { dir ->
TestUtils.executeTaskAndAssertSuccess(
":build",
dir
Expand All @@ -131,23 +145,23 @@ class MultiModulesTests {

@Test
fun `schema targetLanguage propagates`() {
TestUtils.withTestProject("multi-modules-badconfig") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-badconfig") { dir ->
dir.resolve("root/build.gradle.kts").replacePlaceHolder("generateKotlinModels.set(false)")
TestUtils.executeTaskAndAssertSuccess(":leaf:build", dir)
}
}

@Test
fun `schema codegenModels propagates`() {
TestUtils.withTestProject("multi-modules-badconfig") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-badconfig") { dir ->
dir.resolve("root/build.gradle.kts").replacePlaceHolder("codegenModels.set(\"responseBased\")")
TestUtils.executeTaskAndAssertSuccess(":leaf:build", dir)
}
}

@Test
fun `bad targetLanguage is detected`() {
TestUtils.withTestProject("multi-modules-badconfig") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-badconfig") { dir ->
dir.resolve("root/build.gradle.kts").replacePlaceHolder("generateKotlinModels.set(true)")
dir.resolve("leaf/build.gradle.kts").replacePlaceHolder("generateKotlinModels.set(false)")

Expand All @@ -162,7 +176,7 @@ class MultiModulesTests {

@Test
fun `bad codegenModels is detected`() {
TestUtils.withTestProject("multi-modules-badconfig") { dir ->
testProjectWithIsolatedProjectsWorkaround("multi-modules-badconfig") { dir ->
dir.resolve("root/build.gradle.kts").replacePlaceHolder("codegenModels.set(\"responseBased\")")
dir.resolve("leaf/build.gradle.kts").replacePlaceHolder("codegenModels.set(\"operationBased\")")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.gradle.testkit.runner.TaskOutcome
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import util.disableIsolatedProjects
import java.io.File

class AndroidProjectTests {
Expand Down Expand Up @@ -93,6 +94,7 @@ class AndroidProjectTests {
@Test
fun `kotlin Android min version succeeds`() {
withTestProject("kotlin-android-plugin-version") { dir ->
dir.disableIsolatedProjects()
val result = TestUtils.executeTask("build", dir)

Truth.assertThat(result.task(":build")!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
Expand Down
13 changes: 12 additions & 1 deletion libraries/apollo-gradle-plugin/src/test/kotlin/util/TestUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ object TestUtils {
File(dest, "gradle.properties").writeText("""
|org.gradle.jvmargs=-Xmx4g
|
|org.gradle.unsafe.isolated-projects=true
""".trimMargin())

// dest is kept around for debug purposes. All test directories are removed
Expand Down Expand Up @@ -178,7 +179,11 @@ object TestUtils {
.forwardStdOutput(output)
.forwardStdError(error)
.withProjectDir(projectDir)
.withDebug(true)
/*
* Disable withDebug because it breaks with CC
* See https://github.com/gradle/gradle/issues/22765#issuecomment-1339427241
*/
//.withDebug(true)
.withArguments("--stacktrace", *args)
.apply {
if (gradleVersion != null) {
Expand Down Expand Up @@ -216,3 +221,9 @@ fun File.replaceInText(oldValue: Regex, newValue: String) {
val text = readText()
writeText(text.replace(oldValue, newValue))
}

fun File.disableIsolatedProjects() {
resolve("gradle.properties").let {
it.writeText(it.readText().replace("org.gradle.unsafe.isolated-projects=true", ""))
}
}

0 comments on commit d3f6059

Please sign in to comment.