[Gradle IT] Separated adding repositories block and dependencyManagement

In Gradle, there is a bug that leads to race condition,
when we use ivy repo in the settings file.
This bug was solved only in 8.1,
 so we supported dependencyManagement in our IT only since 8.1.
 For Gradle less 8.1 we just add the same repos to build script.

 ^KT-65708 Fixed
This commit is contained in:
Dmitrii Krasnov
2024-02-12 10:32:11 +01:00
committed by Space Team
parent 85399bc969
commit 70a887e3ba
14 changed files with 295 additions and 229 deletions
@@ -183,7 +183,12 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
@DisplayName("with instance execution")
@GradleTest
fun testInstantExecution(gradleVersion: GradleVersion) {
project("instantExecution", gradleVersion) {
project(
"instantExecution",
gradleVersion,
// we can remove this line, when the min version of Gradle be at least 8.1
dependencyManagement = DependencyManagement.DisabledDependencyManagement
) {
testConfigurationCacheOf(
"assemble",
executedTaskNames = listOf(":lib-project:compileKotlin")
@@ -1188,7 +1188,11 @@ open class HierarchicalMppIT : KGPBaseTest() {
@GradleTest
@DisplayName("KT-57531: Kotlin Native Link with cycle in dependency constraints")
fun `test Kotlin Native Link with cycle in dependency constraints`(gradleVersion: GradleVersion) {
project("kt-57531-KotlinNativeLink-with-cycle-in-dependency-constraints", gradleVersion) {
project(
"kt-57531-KotlinNativeLink-with-cycle-in-dependency-constraints",
gradleVersion,
localRepoDir = defaultLocalRepo(gradleVersion)
) {
build("publish")
build("assemble") {
assertTasksExecuted(":consumer:linkDebugExecutableLinuxX64")
@@ -1554,7 +1554,12 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
@DisplayName("test FAIL_ON_PROJECT_REPOS using custom repository")
@GradleTest
fun testFailOnProjectReposUsingCustomRepo(gradleVersion: GradleVersion) {
project("js-project-repos", gradleVersion) {
project(
"js-project-repos",
gradleVersion,
// we can remove this line, when the min version of Gradle be at least 8.1
dependencyManagement = DependencyManagement.DisabledDependencyManagement
) {
settingsGradleKts.modify {
it + """
@@ -1601,7 +1606,12 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
@DisplayName("test FAIL_ON_PROJECT_REPOS no download")
@GradleTest
fun testFailOnProjectReposNoDownload(gradleVersion: GradleVersion) {
project("js-project-repos", gradleVersion) {
project(
"js-project-repos",
gradleVersion,
// we can remove this line, when the min version of Gradle be at least 8.1
dependencyManagement = DependencyManagement.DisabledDependencyManagement
) {
buildGradleKts.modify {
it + """
@@ -24,6 +24,8 @@ class ProjectIsolationIT : KGPBaseTest() {
project(
projectName = "instantExecution",
gradleVersion = gradleVersion,
// we can remove this line, when the min version of Gradle be at least 8.1
dependencyManagement = DependencyManagement.DisabledDependencyManagement
) {
build(":main-project:compileKotlin")
}
@@ -141,7 +141,7 @@ class MppCompositeBuildIT : KGPBaseTest() {
@GradleTest
fun `test - sample1 - ide dependencies`(gradleVersion: GradleVersion) {
project("mpp-composite-build/sample1", gradleVersion) {
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle()
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle(gradleVersion)
buildGradleKts.replaceText("<kgp_version>", KOTLIN_VERSION)
projectPath.resolve("included-build/build.gradle.kts").replaceText("<kgp_version>", KOTLIN_VERSION)
@@ -171,7 +171,7 @@ class MppCompositeBuildIT : KGPBaseTest() {
"mpp-composite-build/sample1",
gradleVersion,
) {
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle()
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle(gradleVersion)
buildGradleKts.replaceText("<kgp_version>", KOTLIN_VERSION)
projectPath.resolve("included-build/build.gradle.kts").replaceText("<kgp_version>", KOTLIN_VERSION)
@@ -203,7 +203,7 @@ class MppCompositeBuildIT : KGPBaseTest() {
reason = "KGP 1.7.21 produces deprecation warnings with Gradle 8.4"
) { gradleVersion >= GradleVersion.version(TestVersions.Gradle.G_8_4) }
) {
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle()
projectPath.resolve("included-build").addDefaultSettingsToSettingsGradle(gradleVersion)
buildGradleKts.replaceText("<kgp_version>", KOTLIN_VERSION)
projectPath.resolve("included-build/build.gradle.kts").replaceText("<kgp_version>", "1.7.21")
@@ -75,94 +75,99 @@ internal fun getGroovyDependencyManagementBlock(
): String =
//language=Groovy
"""
dependencyResolutionManagement {
repositories {
mavenLocal()
mavenCentral()
google()
ivy {
url = "https://download.jetbrains.com/kotlin/native/builds/dev"
patternLayout {
artifact("[revision]/[classifier]/[artifact]-[classifier]-[revision].[ext]")
}
metadataSources {
artifact()
}
}
maven {
url "https://packages.jetbrains.team/maven/p/ij/intellij-dependencies/"
}
ivy {
url = "https://github.com/yarnpkg/yarn/releases/download"
|dependencyResolutionManagement {
| ${getGroovyRepositoryBlock(additionalDependencyRepositories, localRepo)}
| repositoriesMode.set(${mapRepositoryModeToString(gradleRepositoriesMode)})
|}
""".trimMargin()
patternLayout {
artifact("v[revision]/[artifact](-v[revision]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("com.yarnpkg", "yarn")
}
}
ivy {
url = "https://nodejs.org/dist"
patternLayout {
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("org.nodejs", "node")
}
}
ivy {
url = uri("https://nodejs.org/download/v8-canary")
patternLayout {
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("org.nodejs", "node")
}
}
ivy {
url = uri("https://github.com/WebAssembly/binaryen/releases/download")
patternLayout {
artifact("version_[revision]/binaryen-version_[revision]-[classifier].[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("com.github.webassembly", "binaryen")
}
}
ivy {
url = uri("https://storage.googleapis.com/chromium-v8/official/canary")
patternLayout {
artifact("[artifact]-[revision].[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("google.d8", "v8")
}
}
${additionalDependencyRepositories.map { repo -> "maven{ url = \"$repo\" }" }.joinToString("\n")}
${localRepo?.absolutePathString()?.let { repo -> "maven{ url = \"${repo.replace("\\", "\\\\")}\" }" } ?: ""}
}
repositoriesMode.set(${mapRepositoryModeToString(gradleRepositoriesMode)})
}
""".trimIndent()
internal fun getGroovyRepositoryBlock(
additionalDependencyRepositories: Set<String>,
localRepo: Path? = null,
): String =
//language=Groovy
"""
|
| repositories {
| mavenLocal()
| mavenCentral()
| google()
| ivy {
| url = "https://download.jetbrains.com/kotlin/native/builds/dev"
| patternLayout {
| artifact("[revision]/[classifier]/[artifact]-[classifier]-[revision].[ext]")
| }
| metadataSources {
| artifact()
| }
| }
| maven {
| url "https://packages.jetbrains.team/maven/p/ij/intellij-dependencies/"
| }
| ivy {
| url = "https://github.com/yarnpkg/yarn/releases/download"
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("com.yarnpkg", "yarn")
| }
| }
| ivy {
| url = "https://nodejs.org/dist"
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("org.nodejs", "node")
| }
| }
| ivy {
| url = uri("https://nodejs.org/download/v8-canary")
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("org.nodejs", "node")
| }
| }
| ivy {
| url = uri("https://github.com/WebAssembly/binaryen/releases/download")
| patternLayout {
| artifact("version_[revision]/binaryen-version_[revision]-[classifier].[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("com.github.webassembly", "binaryen")
| }
| }
| ivy {
| url = uri("https://storage.googleapis.com/chromium-v8/official/canary")
| patternLayout {
| artifact("[artifact]-[revision].[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("google.d8", "v8")
| }
| }
| ${additionalDependencyRepositories.map { repo -> "maven{ url = \"$repo\" }" }.joinToString("\n")}
| ${localRepo?.absolutePathString()?.let { repo -> "maven{ url = \"${repo.replace("\\", "\\\\")}\" }" } ?: ""}
| }
""".trimMargin()
@Language("kts")
internal val DEFAULT_KOTLIN_SETTINGS_FILE =
@@ -231,95 +236,99 @@ internal fun getKotlinDependencyManagementBlock(
): String =
//language=kotlin
"""
dependencyResolutionManagement {
repositories {
mavenLocal()
mavenCentral()
google()
ivy {
url = uri("https://download.jetbrains.com/kotlin/native/builds/dev")
patternLayout {
artifact("[revision]/[classifier]/[artifact]-[classifier]-[revision].[ext]")
}
metadataSources {
artifact()
}
}
ivy {
url = uri("https://github.com/yarnpkg/yarn/releases/download")
patternLayout {
artifact("v[revision]/[artifact](-v[revision]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("com.yarnpkg", "yarn")
}
}
ivy {
url = uri("https://nodejs.org/dist")
patternLayout {
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("org.nodejs", "node")
}
}
ivy {
url = uri("https://nodejs.org/download/v8-canary")
patternLayout {
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("org.nodejs", "node")
}
}
ivy {
url = uri("https://github.com/WebAssembly/binaryen/releases/download")
patternLayout {
artifact("version_[revision]/binaryen-version_[revision]-[classifier].[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("com.github.webassembly", "binaryen")
}
}
ivy {
url = uri("https://storage.googleapis.com/chromium-v8/official/canary")
patternLayout {
artifact("[artifact]-[revision].[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("google.d8", "v8")
}
}
maven {
url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies/")
}
${additionalDependencyRepositories.map { repo -> "maven{ url = uri(\"$repo\") }" }.joinToString("\n")}
${localRepo?.absolutePathString()?.let { repo -> "maven{ url = uri(\"${repo.replace("\\", "\\\\")}\") }" } ?: ""}
}
repositoriesMode.set(${mapRepositoryModeToString(gradleRepositoriesMode)})
}
""".trimIndent()
|dependencyResolutionManagement {
| ${getKotlinRepositoryBlock(additionalDependencyRepositories, localRepo)}
| repositoriesMode.set(${mapRepositoryModeToString(gradleRepositoriesMode)})
|}
""".trimMargin()
internal fun getKotlinRepositoryBlock(
additionalDependencyRepositories: Set<String>,
localRepo: Path? = null,
): String =
//language=kotlin
"""
|
| repositories {
| mavenLocal()
| mavenCentral()
| google()
| ivy {
| url = uri("https://download.jetbrains.com/kotlin/native/builds/dev")
| patternLayout {
| artifact("[revision]/[classifier]/[artifact]-[classifier]-[revision].[ext]")
| }
| metadataSources {
| artifact()
| }
| }
| ivy {
| url = uri("https://github.com/yarnpkg/yarn/releases/download")
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("com.yarnpkg", "yarn")
| }
| }
| ivy {
| url = uri("https://nodejs.org/dist")
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("org.nodejs", "node")
| }
| }
| ivy {
| url = uri("https://nodejs.org/download/v8-canary")
| patternLayout {
| artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("org.nodejs", "node")
| }
| }
| ivy {
| url = uri("https://github.com/WebAssembly/binaryen/releases/download")
| patternLayout {
| artifact("version_[revision]/binaryen-version_[revision]-[classifier].[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("com.github.webassembly", "binaryen")
| }
| }
| ivy {
| url = uri("https://storage.googleapis.com/chromium-v8/official/canary")
| patternLayout {
| artifact("[artifact]-[revision].[ext]")
| }
| metadataSources {
| artifact()
| }
| content {
| includeModule("google.d8", "v8")
| }
| }
| maven {
| url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies/")
| }
| ${additionalDependencyRepositories.map { repo -> "maven{ url = uri(\"$repo\") }" }.joinToString("\n")}
| ${localRepo?.absolutePathString()?.let { repo -> "maven{ url = uri(\"${repo.replace("\\", "\\\\")}\") }" } ?: ""}
| }
""".trimMargin()
private fun mapRepositoryModeToString(gradleRepositoriesMode: RepositoriesMode): String {
return when (gradleRepositoriesMode) {
@@ -61,7 +61,7 @@ fun KGPBaseTest.project(
workingDir,
projectPathAdditionalSuffix,
)
projectPath.addDefaultSettingsToSettingsGradle(dependencyManagement, localRepoDir)
projectPath.addDefaultSettingsToSettingsGradle(gradleVersion, dependencyManagement, localRepoDir)
projectPath.enableCacheRedirector()
projectPath.enableAndroidSdk()
if (buildOptions.languageVersion != null || buildOptions.languageApiVersion != null) {
@@ -438,7 +438,7 @@ class TestProject(
val otherProjectPath = "$pathPrefix/$otherProjectName".testProjectPath
otherProjectPath.copyRecursively(projectPath.resolve(otherProjectName))
projectPath.resolve(otherProjectName).addDefaultSettingsToSettingsGradle()
projectPath.resolve(otherProjectName).addDefaultSettingsToSettingsGradle(gradleVersion)
settingsGradle.append(
"""
@@ -551,31 +551,97 @@ private fun setupProjectFromTestResources(
private val String.testProjectPath: Path get() = Paths.get("src", "test", "resources", "testProject", this)
internal fun Path.addDefaultSettingsToSettingsGradle(
gradleVersion: GradleVersion,
dependencyManagement: DependencyManagement = DependencyManagement.DefaultDependencyManagement(),
localRepo: Path? = null,
) {
addPluginManagementToSettings()
when (dependencyManagement) {
is DependencyManagement.DefaultDependencyManagement -> addDependencyManagementToSettings(
additionalDependencyRepositories = dependencyManagement.additionalRepos,
localRepo = localRepo
)
is DependencyManagement.DefaultDependencyManagement -> {
// we cannot switch to dependencyManagement before Gradle 8.1 because of KT-65708
if (gradleVersion < GradleVersion.version(TestVersions.Gradle.G_8_1)) {
addDependencyRepositoriesToBuildScript(
additionalDependencyRepositories = dependencyManagement.additionalRepos,
localRepo = localRepo
)
} else {
addDependencyManagementToSettings(
additionalDependencyRepositories = dependencyManagement.additionalRepos,
localRepo = localRepo
)
}
}
is DependencyManagement.DisabledDependencyManagement -> {}
}
}
val buildSrc = resolve("buildSrc")
if (Files.exists(buildSrc)) {
buildSrc.addPluginManagementToSettings()
when (dependencyManagement) {
is DependencyManagement.DefaultDependencyManagement -> buildSrc.addDependencyManagementToSettings(
additionalDependencyRepositories = dependencyManagement.additionalRepos,
localRepo = localRepo
private fun Path.addDependencyRepositoriesToBuildScript(
additionalDependencyRepositories: Set<String>,
localRepo: Path? = null,
) {
val buildGradle = resolve("build.gradle")
val buildGradleKts = resolve("build.gradle.kts")
val settingsGradle = resolve("settings.gradle")
val settingsGradleKts = resolve("settings.gradle.kts")
when {
Files.exists(buildGradle) -> buildGradle.modify {
it.insertBlockToBuildScriptAfterPluginsAndImports(
getGroovyRepositoryBlock(additionalDependencyRepositories, localRepo).wrapWithAllProjectBlock()
)
is DependencyManagement.DisabledDependencyManagement -> {}
}
Files.exists(buildGradleKts) -> buildGradleKts.modify {
it.insertBlockToBuildScriptAfterPluginsAndImports(
getKotlinRepositoryBlock(additionalDependencyRepositories, localRepo).wrapWithAllProjectBlock()
)
}
Files.exists(settingsGradle) -> buildGradle.toFile()
.writeText(
getGroovyRepositoryBlock(
additionalDependencyRepositories,
localRepo
).wrapWithAllProjectBlock()
)
Files.exists(settingsGradleKts) -> buildGradleKts.toFile()
.writeText(
getKotlinRepositoryBlock(
additionalDependencyRepositories,
localRepo
).wrapWithAllProjectBlock()
)
else -> error("No build-file or settings file found")
}
if (Files.exists(resolve("buildSrc"))) {
resolve("buildSrc").addDependencyRepositoriesToBuildScript(additionalDependencyRepositories, localRepo)
}
}
private fun String.wrapWithAllProjectBlock(): String =
"""
|
|allprojects {
| $this
|}
|
""".trimMargin()
private fun String.insertBlockToBuildScriptAfterPluginsAndImports(blockToInsert: String): String {
val importsPattern = Regex("^import.*$", RegexOption.MULTILINE)
val pluginsBlockPattern = Regex("plugins\\s*\\{[^}]*}", RegexOption.DOT_MATCHES_ALL)
val lastImportIndex = importsPattern.findAll(this).map { it.range.last }.maxOrNull()
val pluginBlockEndIndex = pluginsBlockPattern.find(this)?.range?.last
val insertionIndex = listOfNotNull(lastImportIndex, pluginBlockEndIndex).maxOrNull() ?: return blockToInsert + this
return StringBuilder(this).insert(insertionIndex + 1, "\n$blockToInsert\n").toString()
}
internal fun Path.addPluginManagementToSettings() {
val buildGradle = resolve("build.gradle")
val buildGradleKts = resolve("build.gradle.kts")
@@ -641,7 +707,7 @@ internal fun Path.addDependencyManagementToSettings(
localRepo
)
}
|""".trimMargin()
""".trimMargin()
} else {
it
}
@@ -6,11 +6,6 @@ plugins {
allprojects {
group = "a"
version = "1.0"
repositories {
mavenLocal()
mavenCentral()
}
}
kotlin {
@@ -11,7 +11,7 @@ version = "1.0.0"
publishing {
repositories {
maven(rootProject.buildDir.resolve("repo"))
maven("<localRepo>")
}
}
@@ -10,7 +10,7 @@ version = "1.0.0"
publishing {
repositories {
maven(rootProject.buildDir.resolve("repo"))
maven("<localRepo>")
}
}
@@ -1,12 +1,3 @@
dependencyResolutionManagement {
repositories {
maven(rootProject.projectDir.resolve("build").resolve("repo"))
mavenLocal()
mavenCentral()
google()
}
}
include(":p1")
include(":p2")
include(":consumer")
@@ -13,10 +13,6 @@ buildscript {
apply plugin: 'kotlin-multiplatform'
repositories {
mavenLocal()
mavenCentral()
}
kotlin {
targets {
@@ -2,11 +2,6 @@ plugins {
kotlin("multiplatform")
}
repositories {
mavenLocal()
mavenCentral()
}
kotlin {
<SingleNativeTarget>("native") {
binaries.executable()
@@ -1,10 +1,3 @@
plugins {
kotlin("multiplatform").apply(false)
}
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
}