diff --git a/.puppeteerrc.cjs b/.puppeteerrc.cjs index cf9afa888..44011893f 100644 --- a/.puppeteerrc.cjs +++ b/.puppeteerrc.cjs @@ -1,6 +1,6 @@ const {join} = require('path'); -const isCI = process.env.TEAMCITY_VERSION +const isCI = process.env.TEAMCITY_VERSION || process.env.GITHUB_ACTIONS; if (isCI) { /** diff --git a/compiler-plugin/gradle.properties b/compiler-plugin/gradle.properties deleted file mode 120000 index 7677fb73b..000000000 --- a/compiler-plugin/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -../gradle.properties \ No newline at end of file diff --git a/compiler-plugin/gradle.properties b/compiler-plugin/gradle.properties new file mode 100644 index 000000000..b64cbf878 --- /dev/null +++ b/compiler-plugin/gradle.properties @@ -0,0 +1,40 @@ +# +# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. +# + +kotlin.code.style=official + +kotlin.native.ignoreDisabledTargets=true + +kotlin.daemon.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError +kotlin.daemon.useFallbackStrategy=false + +org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=768m +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.workers.max=8 +org.gradle.caching=true +org.gradle.configuration-cache=true + +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true + +# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin +kotlinx.rpc.plugin.internalDevelopment=true + +# uncomment to debug compilation process +#kotlin.compiler.execution.strategy=in-process + +# Uncomment to skip attempts to publish Develocity build scans +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipBuildScans=true + +# Uncomment to skip adding git tags to Develocity build scan +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipGitTags=true + +# Uncomment to sync IDEA when working with Kotlin master builds +#kotlinx.rpc.kotlinMasterBuild=true + +# set to true when building IDE compiler plugin artifacts +kotlinx.rpc.forIdeBuild=false diff --git a/dokka-plugin/gradle.properties b/dokka-plugin/gradle.properties deleted file mode 120000 index 7677fb73b..000000000 --- a/dokka-plugin/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -../gradle.properties \ No newline at end of file diff --git a/dokka-plugin/gradle.properties b/dokka-plugin/gradle.properties new file mode 100644 index 000000000..b64cbf878 --- /dev/null +++ b/dokka-plugin/gradle.properties @@ -0,0 +1,40 @@ +# +# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. +# + +kotlin.code.style=official + +kotlin.native.ignoreDisabledTargets=true + +kotlin.daemon.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError +kotlin.daemon.useFallbackStrategy=false + +org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=768m +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.workers.max=8 +org.gradle.caching=true +org.gradle.configuration-cache=true + +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true + +# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin +kotlinx.rpc.plugin.internalDevelopment=true + +# uncomment to debug compilation process +#kotlin.compiler.execution.strategy=in-process + +# Uncomment to skip attempts to publish Develocity build scans +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipBuildScans=true + +# Uncomment to skip adding git tags to Develocity build scan +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipGitTags=true + +# Uncomment to sync IDEA when working with Kotlin master builds +#kotlinx.rpc.kotlinMasterBuild=true + +# set to true when building IDE compiler plugin artifacts +kotlinx.rpc.forIdeBuild=false diff --git a/gradle-conventions-settings/develocity/src/main/kotlin/conventions-develocity.settings.gradle.kts b/gradle-conventions-settings/develocity/src/main/kotlin/conventions-develocity.settings.gradle.kts index 89f7bd273..027d8d62d 100644 --- a/gradle-conventions-settings/develocity/src/main/kotlin/conventions-develocity.settings.gradle.kts +++ b/gradle-conventions-settings/develocity/src/main/kotlin/conventions-develocity.settings.gradle.kts @@ -16,6 +16,9 @@ develocity { server.set(DEVELOCITY_SERVER) buildScan { + termsOfUseUrl = "https://gradle.com/terms-of-service" + termsOfUseAgree = loadAgreement() + uploadInBackground.set(!isCIRun) // obfuscate NIC since we don't want to expose user real IP (will be relevant without VPN) @@ -35,7 +38,7 @@ develocity { .getOrElse("false") .toBooleanStrict() - publishing.onlyIf { !skipBuildScans } + publishing.onlyIf { termsOfUseAgree.get() == "yes" && !skipBuildScans } } } diff --git a/gradle-conventions-settings/develocity/src/main/kotlin/execute.kt b/gradle-conventions-settings/develocity/src/main/kotlin/execute.kt index fd12377d9..9df72e4a4 100644 --- a/gradle-conventions-settings/develocity/src/main/kotlin/execute.kt +++ b/gradle-conventions-settings/develocity/src/main/kotlin/execute.kt @@ -4,7 +4,6 @@ import org.gradle.api.initialization.Settings -@Suppress("UnstableApiUsage") fun Settings.execute(cmd: String): String { return settings.providers.exec { commandLine(cmd.split(" ")) diff --git a/gradle-conventions-settings/develocity/src/main/kotlin/loadAgreement.kt b/gradle-conventions-settings/develocity/src/main/kotlin/loadAgreement.kt new file mode 100644 index 000000000..454eca75a --- /dev/null +++ b/gradle-conventions-settings/develocity/src/main/kotlin/loadAgreement.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +import org.gradle.api.GradleException +import org.gradle.api.initialization.Settings +import org.gradle.kotlin.dsl.extra +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import kotlin.io.path.bufferedWriter +import kotlin.io.path.createFile +import kotlin.io.path.exists + +private const val TERMS_OF_USE_PROPERTY = "kotlinx.rpc.develocity.termsOfUseAgree" + +fun Settings.loadAgreement(): String { + if (isCIRun) { + return "yes" + } + + val localProperties = extra["localProperties"] as? java.util.Properties + ?: throw GradleException("'local.properties' property not found") + + when (val value = localProperties.getProperty(TERMS_OF_USE_PROPERTY)) { + "yes", "no" -> { + return value + } + + "" -> { + throw GradleException( + "'$TERMS_OF_USE_PROPERTY' property is not set in file://local.properties'. " + + "Please set this property to 'yes' or 'no'." + ) + } + + null -> { + val globalRootDir = extra["globalRootDir"] as? String + ?: throw GradleException("'globalRootDir' property not found. Contact developers.") + + val propFile = Path.of(globalRootDir).resolve("local.properties") + if (!propFile.exists()) { + propFile.createFile() + } + + propFile.bufferedWriter(Charsets.UTF_8, bufferSize = 1024, StandardOpenOption.APPEND).use { writer -> + writer.appendLine() + writer.appendLine("# Terms of Gradle use agreement: https://gradle.com/terms-of-service") + writer.appendLine("# Set to yes or no") + writer.appendLine("# Only needed for JetBrains maintainers") + writer.appendLine("$TERMS_OF_USE_PROPERTY=") + } + + throw GradleException( + "'$TERMS_OF_USE_PROPERTY' property not found in file://local.properties . " + + "Please add this property and set it to 'yes' or 'no'." + ) + } + + else -> { + throw GradleException( + "Invalid value for '$TERMS_OF_USE_PROPERTY' property: $value. " + + "Please set this property to 'yes' or 'no'." + ) + } + } +} diff --git a/gradle-conventions-settings/develocity/src/main/kotlin/params.kt b/gradle-conventions-settings/develocity/src/main/kotlin/params.kt index cb3a017a6..e45b27367 100644 --- a/gradle-conventions-settings/develocity/src/main/kotlin/params.kt +++ b/gradle-conventions-settings/develocity/src/main/kotlin/params.kt @@ -6,4 +6,4 @@ const val DEVELOCITY_SERVER = "https://ge.jetbrains.com" const val GITHUB_REPO = "https://github.com/Kotlin/kotlinx-rpc" const val TEAMCITY_URL = "https://krpc.teamcity.com" -val isCIRun = System.getenv("TEAMCITY_VERSION") != null +val isCIRun = System.getenv("TEAMCITY_VERSION") != null || System.getenv("GITHUB_ACTIONS") != null diff --git a/gradle-conventions-settings/src/main/kotlin/conventions-repositories.settings.gradle.kts b/gradle-conventions-settings/src/main/kotlin/conventions-repositories.settings.gradle.kts index 37630bdae..f7c468fb4 100644 --- a/gradle-conventions-settings/src/main/kotlin/conventions-repositories.settings.gradle.kts +++ b/gradle-conventions-settings/src/main/kotlin/conventions-repositories.settings.gradle.kts @@ -38,6 +38,7 @@ pluginManagement { .removeSuffix("/gradle-conventions-settings") .removeSuffix("/compiler-plugin") .removeSuffix("/gradle-plugin") + .removeSuffix("/dokka-plugin") ) val localFile = File(propertiesDir, "local.properties") if (localFile.exists()) { @@ -100,94 +101,99 @@ pluginManagement { } } -gradle.rootProject { - fun findGlobalRootDirPath(): java.nio.file.Path { - var path = file(".").toPath().toAbsolutePath() +fun findGlobalRootDirPath(): java.nio.file.Path { + var path = file(".").toPath().toAbsolutePath() - // we assume that the 'versions-root' folder can only be present in the root folder - while ( - java.nio.file.Files.newDirectoryStream(path).use { it.toList() }.none { - java.nio.file.Files.isDirectory(it) && it.fileName.toString() == "versions-root" - } - ) { - path = path.parent ?: error("Unable to find root path for kotlinx.rpc project") + // we assume that the 'versions-root' folder can only be present in the root folder + while ( + java.nio.file.Files.newDirectoryStream(path).use { it.toList() }.none { + java.nio.file.Files.isDirectory(it) && it.fileName.toString() == "versions-root" } - - return path + ) { + path = path.parent ?: error("Unable to find root path for kotlinx.rpc project") } - fun logAbsentProperty(name: String): Nothing? { - logger.info("Property '$name' is not present for repository credentials.") + return path +} - return null - } +fun logAbsentProperty(name: String): Nothing? { + logger.info("Property '$name' is not present for repository credentials.") - fun getEnv(propertyName: String): String? = System.getenv( - propertyName.replace(".", "_").uppercase() - )?.ifEmpty { null } + return null +} - fun getLocalProperties(): java.util.Properties { - return java.util.Properties().apply { - val propertiesDir = File( - rootDir.path - .removeSuffix("/gradle-conventions") - .removeSuffix("/gradle-conventions-settings") - .removeSuffix("/compiler-plugin") - .removeSuffix("/gradle-plugin") - ) - val localFile = File(propertiesDir, "local.properties") - if (localFile.exists()) { - localFile.inputStream().use { load(it) } - } +fun getEnv(propertyName: String): String? = System.getenv( + propertyName.replace(".", "_").uppercase() +)?.ifEmpty { null } + +fun getLocalProperties(): java.util.Properties { + return java.util.Properties().apply { + val propertiesDir = File( + rootDir.path + .removeSuffix("/gradle-conventions") + .removeSuffix("/gradle-conventions-settings") + .removeSuffix("/compiler-plugin") + .removeSuffix("/gradle-plugin") + .removeSuffix("/dokka-plugin") + ) + val localFile = File(propertiesDir, "local.properties") + if (localFile.exists()) { + localFile.inputStream().use { load(it) } } } +} - fun java.util.Properties.isUsingProxyRepositories(): Boolean { - val useProxyProperty = this["kotlinx.rpc.useProxyRepositories"] as String? - return useProxyProperty == null || useProxyProperty == "true" - } +fun java.util.Properties.isUsingProxyRepositories(): Boolean { + val useProxyProperty = this["kotlinx.rpc.useProxyRepositories"] as String? + return useProxyProperty == null || useProxyProperty == "true" +} - fun getSpacePassword(): String? { - val password = "kotlinx.rpc.team.space.password" - return getLocalProperties()[password] as String? - ?: settings.providers.gradleProperty(password).orNull - ?: getEnv(password) - ?: logAbsentProperty(password) - } +fun getSpacePassword(): String? { + val password = "kotlinx.rpc.team.space.password" + return getLocalProperties()[password] as String? + ?: settings.providers.gradleProperty(password).orNull + ?: getEnv(password) + ?: logAbsentProperty(password) +} - /** - * Creates a publishing repository targeting Space Packages on jetbrains.team. - * - * @param repoName the name of the Space Packages repository - */ - fun RepositoryHandler.jbTeamPackages(repoName: String) { - maven { - name = repoName.split("-").joinToString("") { it.replaceFirstChar { c -> c.titlecase() } } - url = uri("https://packages.jetbrains.team/maven/p/krpc/$repoName") +/** + * Creates a publishing repository targeting Space Packages on jetbrains.team. + * + * @param repoName the name of the Space Packages repository + */ +fun RepositoryHandler.jbTeamPackages(repoName: String) { + maven { + name = repoName.split("-").joinToString("") { it.replaceFirstChar { c -> c.titlecase() } } + url = uri("https://packages.jetbrains.team/maven/p/krpc/$repoName") - val spacePassword = getSpacePassword() + val spacePassword = getSpacePassword() - if (spacePassword != null) { - credentials(HttpHeaderCredentials::class.java) { - name = "Authorization" - value = "Bearer $spacePassword" - } + if (spacePassword != null) { + credentials(HttpHeaderCredentials::class.java) { + name = "Authorization" + value = "Bearer $spacePassword" + } - authentication { - create("http_auth_header") - } - } else { - logger.info("Skipping adding credentials for Space repository '$repoName'") + authentication { + create("http_auth_header") } + } else { + logger.info("Skipping adding credentials for Space repository '$repoName'") } } +} - fun RepositoryHandler.buildDeps() = jbTeamPackages(repoName = "build-deps") - fun RepositoryHandler.buildDepsEap() = jbTeamPackages(repoName = "build-deps-eap") +fun RepositoryHandler.buildDeps() = jbTeamPackages(repoName = "build-deps") +fun RepositoryHandler.buildDepsEap() = jbTeamPackages(repoName = "build-deps-eap") - allprojects { - val localProps = getLocalProperties() +val localProps = getLocalProperties() + +settings.extra["spacePassword"] = getSpacePassword() +settings.extra["localProperties"] = localProps +settings.extra["useProxyRepositories"] = localProps.isUsingProxyRepositories() +gradle.rootProject { + allprojects { this.extra["spacePassword"] = getSpacePassword() this.extra["localProperties"] = localProps this.extra["useProxyRepositories"] = localProps.isUsingProxyRepositories() diff --git a/gradle-conventions-settings/src/main/kotlin/conventions-version-resolution.settings.gradle.kts b/gradle-conventions-settings/src/main/kotlin/conventions-version-resolution.settings.gradle.kts index 59134a212..596b91d9a 100644 --- a/gradle-conventions-settings/src/main/kotlin/conventions-version-resolution.settings.gradle.kts +++ b/gradle-conventions-settings/src/main/kotlin/conventions-version-resolution.settings.gradle.kts @@ -64,6 +64,8 @@ fun findGlobalRootDirPath(start: Path): Path { } } + settings.extra["globalRootDir"] = path.toAbsolutePath().toString() + return path } diff --git a/gradle-conventions/src/main/kotlin/conventions-root.gradle.kts b/gradle-conventions/src/main/kotlin/conventions-root.gradle.kts index 8eda2d086..d73b02f87 100644 --- a/gradle-conventions/src/main/kotlin/conventions-root.gradle.kts +++ b/gradle-conventions/src/main/kotlin/conventions-root.gradle.kts @@ -9,6 +9,13 @@ import util.tasks.registerChangelogTask import util.tasks.registerDumpPlatformTableTask import util.tasks.registerVerifyPlatformTableTask import java.time.Year +import kotlin.io.path.exists +import kotlin.io.path.isDirectory +import kotlin.io.path.listDirectoryEntries +import kotlin.io.path.name +import kotlin.io.path.readText +import java.nio.file.Path +import kotlin.io.path.createFile plugins { id("org.jetbrains.dokka") @@ -81,3 +88,43 @@ configureNpm() registerDumpPlatformTableTask() registerVerifyPlatformTableTask() registerChangelogTask() + +fun Project.forEachSubproject(action: (String, Path, Path) -> Unit) { + val globalRootDir: String by extra + val root = Path.of(globalRootDir) + val rootProperties = root.resolve("gradle.properties").readText() + root.listDirectoryEntries() + .filter { it.isDirectory() && it.name != "gradle-conventions-settings" && it.name != "gradle-conventions" } + .forEach { + val subProjectProperties = it.resolve("gradle.properties") + val subProjectSettings = it.resolve("settings.gradle.kts") + if (subProjectSettings.exists()) { + action(rootProperties, it, subProjectProperties) + } + } +} + +val updateProperties = tasks.register("updateProperties") { + forEachSubproject { rootProperties, _, subProjectProperties -> + if (!subProjectProperties.exists()) { + subProjectProperties.createFile() + } + + subProjectProperties.toFile().writeText(rootProperties) + } +} + +gradle.afterProject { + if (gradle.startParameter.taskNames.singleOrNull() == updateProperties.name) { + return@afterProject + } + + forEachSubproject { rootProperties, parent, subProjectProperties -> + if (!subProjectProperties.exists() || subProjectProperties.readText() != rootProperties) { + throw GradleException( + "'gradle.properties' file in ${parent.name} included project is not up-to-date with root. " + + "Please, run `./gradlew ${updateProperties.name}" + ) + } + } +} diff --git a/gradle-plugin/build.gradle.kts b/gradle-plugin/build.gradle.kts index 49981028a..8390f7176 100644 --- a/gradle-plugin/build.gradle.kts +++ b/gradle-plugin/build.gradle.kts @@ -2,7 +2,6 @@ * Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ -import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode plugins { `kotlin-dsl` diff --git a/gradle-plugin/gradle.properties b/gradle-plugin/gradle.properties deleted file mode 120000 index 7677fb73b..000000000 --- a/gradle-plugin/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -../gradle.properties \ No newline at end of file diff --git a/gradle-plugin/gradle.properties b/gradle-plugin/gradle.properties new file mode 100644 index 000000000..b64cbf878 --- /dev/null +++ b/gradle-plugin/gradle.properties @@ -0,0 +1,40 @@ +# +# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. +# + +kotlin.code.style=official + +kotlin.native.ignoreDisabledTargets=true + +kotlin.daemon.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError +kotlin.daemon.useFallbackStrategy=false + +org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=768m +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.workers.max=8 +org.gradle.caching=true +org.gradle.configuration-cache=true + +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true + +# development mode for kotlinx.rpc gradle plugin. Uses local project paths to apply the compiler plugin +kotlinx.rpc.plugin.internalDevelopment=true + +# uncomment to debug compilation process +#kotlin.compiler.execution.strategy=in-process + +# Uncomment to skip attempts to publish Develocity build scans +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipBuildScans=true + +# Uncomment to skip adding git tags to Develocity build scan +# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes +#kotlinx.rpc.develocity.skipGitTags=true + +# Uncomment to sync IDEA when working with Kotlin master builds +#kotlinx.rpc.kotlinMasterBuild=true + +# set to true when building IDE compiler plugin artifacts +kotlinx.rpc.forIdeBuild=false diff --git a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt index a46c1548f..2c90c61ea 100644 --- a/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt +++ b/krpc/krpc-test/src/jvmTest/kotlin/kotlinx/rpc/krpc/test/api/util/GoldChecks.kt @@ -116,7 +116,8 @@ private fun goldFileLine(goldPath: String?): String { } } -private val isCI = System.getenv("TEAMCITY_VERSION") != null +private val isCI = System.getenv("TEAMCITY_VERSION") != null || + System.getenv("GITHUB_ACTIONS") != null object GoldUtils { val NewLine: String = System.lineSeparator() diff --git a/tests/compiler-plugin-tests/build.gradle.kts b/tests/compiler-plugin-tests/build.gradle.kts index b20d7b0b6..095972f1b 100644 --- a/tests/compiler-plugin-tests/build.gradle.kts +++ b/tests/compiler-plugin-tests/build.gradle.kts @@ -141,7 +141,7 @@ val generateTests = tasks.register("generateTests") { mainClass.set("kotlinx.rpc.codegen.test.GenerateTestsKt") } -val isCI = System.getenv("TEAMCITY_VERSION") != null +val isCI = System.getenv("TEAMCITY_VERSION") != null || System.getenv("GITHUB_ACTIONS") != null tasks.named("compileTestKotlin").configure { if (!isCI) {