a14d0d148b
Move all the code to apply Kotlin bootstrap into settings script plugin which does following: - configures based either on the repo root 'local.properties' or on the root project gradle properties or on the repo root 'gradle.properties' current type of bootstrap - automatically adds Kotlin bootstrap repository with exclusive content, so bootstrap dependencies will not be by mistake downloaded from other repository - automatically forces all Kotlin plugins applied in the build to use bootstrap version This script should be applied only in project settings.gradle and then it does all the configuration by itself.
303 lines
12 KiB
Kotlin
303 lines
12 KiB
Kotlin
/*
|
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
*/
|
|
|
|
// Apply this settings script in the project settings.gradle following way:
|
|
// pluginManagement {
|
|
// apply from: 'kotlin-bootstrap.settings.gradle.kts'
|
|
// }
|
|
|
|
import java.util.Properties
|
|
import org.gradle.api.internal.GradleInternal
|
|
|
|
object Config {
|
|
const val LOCAL_BOOTSTRAP = "bootstrap.local"
|
|
const val LOCAL_BOOTSTRAP_VERSION = "bootstrap.local.version"
|
|
const val LOCAL_BOOTSTRAP_PATH = "bootstrap.local.path"
|
|
|
|
const val TEAMCITY_BOOTSTRAP_VERSION = "bootstrap.teamcity.kotlin.version"
|
|
const val TEAMCITY_BOOTSTRAP_BUILD_NUMBER = "bootstrap.teamcity.build.number"
|
|
const val TEAMCITY_BOOTSTRAP_PROJECT = "bootstrap.teamcity.project"
|
|
const val TEAMCITY_BOOTSTRAP_URL = "bootstrap.teamcity.url"
|
|
|
|
const val CUSTOM_BOOTSTRAP_VERSION = "bootstrap.kotlin.version"
|
|
const val CUSTOM_BOOTSTRAP_REPO = "bootstrap.kotlin.repo"
|
|
|
|
const val DEFAULT_SNAPSHOT_VERSION = "defaultSnapshotVersion"
|
|
const val DEFAULT_BOOTSTRAP_VERSION = "bootstrap.kotlin.default.version"
|
|
|
|
const val PROJECT_KOTLIN_VERSION = "bootstrapKotlinVersion"
|
|
const val PROJECT_KOTLIN_REPO = "bootstrapKotlinRepo"
|
|
|
|
const val IS_JPS_BUILD_ENABLED = "jpsBuild"
|
|
}
|
|
|
|
abstract class PropertiesValueSource : ValueSource<Properties, PropertiesValueSource.Parameters> {
|
|
interface Parameters : ValueSourceParameters {
|
|
val fileName: Property<String>
|
|
val rootDir: Property<File>
|
|
}
|
|
|
|
override fun obtain(): Properties? {
|
|
val localPropertiesFile = parameters.rootDir.get().resolve(parameters.fileName.get())
|
|
return if (localPropertiesFile.exists()) {
|
|
localPropertiesFile.bufferedReader().use {
|
|
Properties().apply { load(it) }
|
|
}
|
|
} else {
|
|
null
|
|
}
|
|
}
|
|
}
|
|
|
|
fun getRootSettings(
|
|
settings: Settings,
|
|
gradle: Gradle
|
|
): Settings {
|
|
// Gradle interface neither exposes flag if it is a root of composite-build hierarchy
|
|
// nor gives access to Settings object. Fortunately it is availaibe inside GradleInternal internal api
|
|
// used by build scan plugin.
|
|
val gradleInternal = (gradle as GradleInternal)
|
|
return if (gradleInternal.isRootBuild()) {
|
|
settings
|
|
} else {
|
|
val gradleParent = gradle.parent ?: error("Could not get includedBuild parent build for ${settings.rootDir}!")
|
|
getRootSettings(gradle.parent!!.settings, gradle.parent!!)
|
|
}
|
|
}
|
|
|
|
val rootSettings = getRootSettings(settings, settings.gradle)
|
|
|
|
// Workaround for the case when included build could be run directly via --project-dir option.
|
|
// In this case `rootSettings.rootDir` will point to --project-dir location rather then Kotlin repo real root.
|
|
// So in such case script falls back to manual mapping
|
|
val kotlinRootDir: File = when (rootSettings.rootProject.name) {
|
|
"buildSrc" -> {
|
|
val parentDir = rootSettings.rootDir.parentFile
|
|
when (parentDir.name) {
|
|
"benchmarksAnalyzer", "performance-server" -> parentDir.parentFile.parentFile.parentFile
|
|
"performance" -> parentDir.parentFile.parentFile
|
|
"ui" -> parentDir.parentFile.parentFile.parentFile.parentFile
|
|
else -> parentDir
|
|
}
|
|
}
|
|
"benchmarksAnalyzer", "performance-server" -> rootSettings.rootDir.parentFile.parentFile.parentFile
|
|
"performance" -> rootSettings.rootDir.parentFile.parentFile
|
|
"ui" -> rootSettings.rootDir.parentFile.parentFile.parentFile.parentFile
|
|
else -> rootSettings.rootDir
|
|
}
|
|
|
|
private val localProperties = providers.of(PropertiesValueSource::class.java) {
|
|
parameters {
|
|
fileName.set("local.properties")
|
|
rootDir.set(kotlinRootDir)
|
|
}
|
|
}.forUseAtConfigurationTime()
|
|
|
|
private val rootGradleProperties = providers.of(PropertiesValueSource::class.java) {
|
|
parameters {
|
|
fileName.set("gradle.properties")
|
|
rootDir.set(kotlinRootDir)
|
|
}
|
|
}.forUseAtConfigurationTime()
|
|
|
|
fun loadLocalOrGradleProperty(
|
|
propertyName: String
|
|
): Provider<String> {
|
|
// Workaround for https://github.com/gradle/gradle/issues/19114
|
|
// as in the includedBuild GradleProperties are empty on configuration cache reuse
|
|
return if ((gradle as GradleInternal).isRootBuild()) {
|
|
localProperties.map { it.getProperty(propertyName) }.forUseAtConfigurationTime()
|
|
.orElse(providers.gradleProperty(propertyName).forUseAtConfigurationTime())
|
|
.orElse(rootGradleProperties.map { it.getProperty(propertyName) }.forUseAtConfigurationTime())
|
|
} else {
|
|
localProperties.map { it.getProperty(propertyName) }.forUseAtConfigurationTime()
|
|
.orElse(rootSettings.providers.gradleProperty(propertyName).forUseAtConfigurationTime())
|
|
.orElse(rootGradleProperties.map { it.getProperty(propertyName) }.forUseAtConfigurationTime())
|
|
}
|
|
}
|
|
|
|
fun Project.logBootstrapApplied(message: String) {
|
|
if (this == rootProject) logger.lifecycle(message) else logger.info(message)
|
|
}
|
|
|
|
fun String?.propValueToBoolean(default: Boolean = false): Boolean {
|
|
return when {
|
|
this == null -> default
|
|
isEmpty() -> true // has property without value means 'true'
|
|
else -> trim().toBoolean()
|
|
}
|
|
}
|
|
|
|
fun Provider<String>.mapToBoolean(): Provider<Boolean> = map { it?.propValueToBoolean() }
|
|
|
|
fun RepositoryHandler.addBootstrapRepo(
|
|
bootstrapRepo: String,
|
|
bootstrapVersion: String,
|
|
additionalBootstrapRepos: List<String> = emptyList()
|
|
) {
|
|
exclusiveContent {
|
|
forRepositories(
|
|
*(listOf(bootstrapRepo) + additionalBootstrapRepos)
|
|
.map {
|
|
maven { url = uri(it) }
|
|
}
|
|
.toTypedArray()
|
|
)
|
|
filter {
|
|
// kotlin-build-gradle-plugin and non bootstrap-versions
|
|
// should be excluded from strict content filtering
|
|
includeVersionByRegex(
|
|
"org\\.jetbrains\\.kotlin",
|
|
"^(?!kotlin-build-gradle-plugin).*$",
|
|
bootstrapVersion.toRegex().pattern
|
|
)
|
|
|
|
// Kotlin Gradle plugins that have slightly separate maven coordinates
|
|
includeVersionByRegex(
|
|
"org\\.jetbrains\\.kotlin\\..*$",
|
|
"org\\.jetbrains\\.kotlin\\..*\\.gradle\\.plugin$",
|
|
bootstrapVersion.toRegex().pattern
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
|
fun getAdditionalBootstrapRepos(
|
|
bootstrapRepo: String,
|
|
bootstrapKotlinVersion: String,
|
|
isJpsBuildEnabled: Boolean
|
|
): List<String> {
|
|
return buildList {
|
|
if (bootstrapRepo.startsWith("https://buildserver.labs.intellij.net")
|
|
|| bootstrapRepo.startsWith("https://teamcity.jetbrains.com")) {
|
|
add(bootstrapRepo.replace("artifacts/content/maven", "artifacts/content/internal/repo"))
|
|
}
|
|
|
|
if (isJpsBuildEnabled) {
|
|
add(
|
|
"https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_KotlinPublic_Aggregate)," +
|
|
"number:$bootstrapKotlinVersion,branch:default:any/artifacts/content/internal/repo/"
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun Settings.applyBootstrapConfiguration(
|
|
bootstrapVersion: String,
|
|
bootstrapRepo: String,
|
|
isJpsBuildEnabled: Boolean,
|
|
logMessage: String
|
|
) {
|
|
settings.pluginManagement.repositories.addBootstrapRepo(bootstrapRepo, bootstrapVersion)
|
|
settings.pluginManagement.resolutionStrategy.eachPlugin {
|
|
if (requested.id.id.startsWith("org.jetbrains.kotlin.")) {
|
|
useVersion(bootstrapVersion)
|
|
}
|
|
}
|
|
|
|
val additionalRepos = getAdditionalBootstrapRepos(bootstrapRepo, bootstrapVersion, isJpsBuildEnabled)
|
|
gradle.beforeProject {
|
|
bootstrapKotlinVersion = bootstrapVersion
|
|
bootstrapKotlinRepo = bootstrapRepo
|
|
|
|
repositories.addBootstrapRepo(bootstrapRepo, bootstrapVersion, additionalRepos)
|
|
|
|
logBootstrapApplied(logMessage)
|
|
}
|
|
}
|
|
|
|
val isLocalBootstrapEnabled: Provider<Boolean> = loadLocalOrGradleProperty(Config.LOCAL_BOOTSTRAP)
|
|
.mapToBoolean().orElse(false).forUseAtConfigurationTime()
|
|
|
|
val localBootstrapVersion: Provider<String> = loadLocalOrGradleProperty(Config.LOCAL_BOOTSTRAP_VERSION)
|
|
.orElse(loadLocalOrGradleProperty(Config.DEFAULT_SNAPSHOT_VERSION))
|
|
|
|
val localBootstrapPath: Provider<String> = loadLocalOrGradleProperty(Config.LOCAL_BOOTSTRAP_PATH)
|
|
val teamCityBootstrapVersion = loadLocalOrGradleProperty(Config.TEAMCITY_BOOTSTRAP_VERSION)
|
|
val teamCityBootstrapBuildNumber = loadLocalOrGradleProperty(Config.TEAMCITY_BOOTSTRAP_BUILD_NUMBER)
|
|
val teamCityBootstrapProject = loadLocalOrGradleProperty(Config.TEAMCITY_BOOTSTRAP_PROJECT)
|
|
val teamCityBootstrapUrl = loadLocalOrGradleProperty(Config.TEAMCITY_BOOTSTRAP_URL)
|
|
val customBootstrapVersion = loadLocalOrGradleProperty(Config.CUSTOM_BOOTSTRAP_VERSION)
|
|
val customBootstrapRepo = loadLocalOrGradleProperty(Config.CUSTOM_BOOTSTRAP_REPO)
|
|
val defaultBootstrapVersion = loadLocalOrGradleProperty(Config.DEFAULT_BOOTSTRAP_VERSION)
|
|
val isJpsBuildEnabled = loadLocalOrGradleProperty(Config.IS_JPS_BUILD_ENABLED)
|
|
.mapToBoolean().orElse(false).forUseAtConfigurationTime()
|
|
|
|
var Project.bootstrapKotlinVersion: String
|
|
get() = property(Config.PROJECT_KOTLIN_VERSION) as String
|
|
set(value) {
|
|
extensions.extraProperties.set(Config.PROJECT_KOTLIN_VERSION, value)
|
|
}
|
|
|
|
var Project.bootstrapKotlinRepo: String?
|
|
get() = property(Config.PROJECT_KOTLIN_REPO) as String?
|
|
set(value) {
|
|
extensions.extraProperties.set(Config.PROJECT_KOTLIN_REPO, value)
|
|
}
|
|
|
|
// Get bootstrap kotlin version and repository url
|
|
// and set it using pluginManagement and dependencyManangement
|
|
when {
|
|
isLocalBootstrapEnabled.get() -> {
|
|
val bootstrapVersion = localBootstrapVersion.get()
|
|
|
|
val localPath = localBootstrapPath.orNull
|
|
val rootDirectory = rootSettings.rootDir
|
|
val repoPath = if (localPath != null) {
|
|
rootDirectory.resolve(localPath).canonicalFile
|
|
} else {
|
|
rootDirectory.resolve("build").resolve("repo")
|
|
}
|
|
val bootstrapRepo = repoPath.toURI().toString()
|
|
|
|
applyBootstrapConfiguration(
|
|
bootstrapVersion,
|
|
bootstrapRepo,
|
|
isJpsBuildEnabled.get(),
|
|
"Using Kotlin local bootstrap version $bootstrapVersion from $bootstrapRepo"
|
|
)
|
|
}
|
|
teamCityBootstrapVersion.orNull != null -> {
|
|
val bootstrapVersion = teamCityBootstrapVersion.get()
|
|
|
|
val query = "branch:default:any"
|
|
val baseRepoUrl = teamCityBootstrapUrl.orNull ?: "https://buildserver.labs.intellij.net"
|
|
val teamCityProjectId = teamCityBootstrapProject.orNull ?: "Kotlin_KotlinDev_Compiler"
|
|
val teamCityBuildNumber = teamCityBootstrapBuildNumber.orNull ?: bootstrapVersion
|
|
|
|
val bootstrapRepo = "$baseRepoUrl/guestAuth/app/rest/builds/buildType:(id:$teamCityProjectId),number:$teamCityBuildNumber,$query/artifacts/content/maven/"
|
|
|
|
applyBootstrapConfiguration(
|
|
bootstrapVersion,
|
|
bootstrapRepo,
|
|
isJpsBuildEnabled.get(),
|
|
"Using Kotlin TeamCity bootstrap version $bootstrapVersion from $bootstrapRepo"
|
|
)
|
|
}
|
|
customBootstrapVersion.orNull != null -> {
|
|
val bootstrapVersion = customBootstrapVersion.get()
|
|
val bootstrapRepo = customBootstrapRepo.get()
|
|
|
|
applyBootstrapConfiguration(
|
|
bootstrapVersion,
|
|
bootstrapRepo,
|
|
isJpsBuildEnabled.get(),
|
|
"Using Kotlin custom bootstrap version $bootstrapVersion from $bootstrapRepo"
|
|
)
|
|
}
|
|
else -> {
|
|
val bootstrapVersion = defaultBootstrapVersion.get()
|
|
val bootstrapRepo = "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap"
|
|
|
|
applyBootstrapConfiguration(
|
|
bootstrapVersion,
|
|
bootstrapRepo,
|
|
isJpsBuildEnabled.get(),
|
|
"Using Kotlin Space bootstrap version $bootstrapVersion from $bootstrapRepo"
|
|
)
|
|
}
|
|
}
|