Refactor readme logic

This commit is contained in:
2025-10-08 08:51:33 +03:00
parent a854a8e3a2
commit cb0e32eb68
7 changed files with 108 additions and 82 deletions

View File

@@ -10,12 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- WasmWasi target
### Changed
- Kotlin 2.3.0
- Maturity moved to kscience extension.
- Readme extension now requires kscience extension.
### Deprecated
### Removed
### Fixed
- Context parameter flag
### Security

View File

@@ -26,7 +26,6 @@ dependencies {
api("org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlin.asProvider().get()}")
api("org.gradle.toolchains:foojay-resolver:1.0.0")
api("com.vanniktech:gradle-maven-publish-plugin:0.34.0")
api("org.jetbrains.kotlinx:binary-compatibility-validator:0.18.0")
api("org.jetbrains.intellij.plugins:gradle-changelog-plugin:${libs.versions.changelog.get()}")
api("org.jetbrains.dokka:dokka-gradle-plugin:${libs.versions.dokka.get()}")
@@ -159,6 +158,7 @@ mavenPublishing {
}
kotlin {
abiValidation
explicitApiWarning()
jvmToolchain(21)
}

View File

@@ -2,7 +2,7 @@
# @pin
kotlin = "2.3.0-Beta1"
# @pin
tools = "0.19.3-kotlin-2.3.0-Beta1"
tools = "0.20.0-kotlin-2.3.0-Beta1"
atomicfu = "0.29.0"
changelog = "2.4.0"
compose = "1.9.0"

View File

@@ -38,6 +38,13 @@ public enum class DependencySourceSet(public val setName: String, public val suf
TEST("test", "Test")
}
public enum class Maturity {
PROTOTYPE,
EXPERIMENTAL,
DEVELOPMENT,
STABLE,
DEPRECATED
}
/**
* Check if this project version has a development tag (`development` property to true, "dev" in the middle or "SNAPSHOT" in the end).
@@ -48,6 +55,14 @@ public val Project.isInDevelopment: Boolean
|| version.toString().endsWith("SNAPSHOT")
/**
* Check if the project has a kscience extension that declares it as immature. Returns true if the project does not have readme extension
*/
public fun Project.isMature(): Boolean = extensions.findByType<KScienceExtension>()?.let { ext ->
ext.maturity != Maturity.EXPERIMENTAL && ext.maturity != Maturity.PROTOTYPE && ext.maturity != Maturity.DEPRECATED
} ?: true
private const val defaultJdkVersion = 21
public abstract class KScienceExtension @Inject constructor(public val project: Project) : ExtensionAware {
@@ -58,6 +73,9 @@ public abstract class KScienceExtension @Inject constructor(public val project:
public var jdkVersion: Int by jdkVersionProperty
public var maturity: Maturity = Maturity.EXPERIMENTAL
/**
* Use coroutines-core with default version or [version]
*/

View File

@@ -2,8 +2,6 @@ package space.kscience.gradle
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.MavenPublishBasePlugin
import kotlinx.validation.ApiValidationExtension
import kotlinx.validation.BinaryCompatibilityValidatorPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.publish.maven.MavenPom
@@ -14,6 +12,8 @@ import org.jetbrains.changelog.ChangelogPlugin
import org.jetbrains.changelog.ChangelogPluginExtension
import org.jetbrains.dokka.gradle.AbstractDokkaTask
import org.jetbrains.dokka.gradle.DokkaPlugin
import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationExtension
import org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.targets.wasm.yarn.WasmYarnRootExtension
import space.kscience.gradle.internal.addPublishing
import space.kscience.gradle.internal.setupPublication
import space.kscience.gradle.internal.withKScience
import space.kscience.gradle.internal.withKotlin
/**
* Simplifies adding repositories for Maven publishing, responds for releasing tasks for projects.
@@ -95,10 +96,11 @@ public class KSciencePublishingExtension(public val project: Project) {
* generation.
*/
public open class KScienceProjectPlugin : Plugin<Project> {
@OptIn(ExperimentalAbiValidation::class)
override fun apply(target: Project): Unit = target.run {
apply<ChangelogPlugin>()
apply<DokkaPlugin>()
apply<BinaryCompatibilityValidatorPlugin>()
val ksciencePublish = KSciencePublishingExtension(this)
extensions.add("ksciencePublish", ksciencePublish)
@@ -107,7 +109,17 @@ public open class KScienceProjectPlugin : Plugin<Project> {
extensions.add("publish", ksciencePublish)
}
afterEvaluate {
if (!isInDevelopment) {
configure<ChangelogPluginExtension> {
version.set(project.version.toString())
}
}
}
allprojects {
//Add repositories
repositories {
mavenCentral()
maven("https://repo.kotlin.link")
@@ -118,68 +130,67 @@ public open class KScienceProjectPlugin : Plugin<Project> {
tasks.withType<AbstractPublishToMaven>().configureEach {
mustRunAfter(tasks.withType<Sign>())
}
}
afterEvaluate {
if (isInDevelopment) {
configure<ApiValidationExtension> {
validationDisabled = true
}
} else {
configure<ChangelogPluginExtension> {
version.set(project.version.toString())
}
}
}
//Add readme generators to individual subprojects and root project
allprojects {
val readmeExtension = KScienceReadmeExtension(this)
extensions.add("readme", readmeExtension)
withKScience {
//Add readme generators to individual subprojects and root project
val readmeExtension = KScienceReadmeExtension(this)
project.extensions.add("readme", readmeExtension)
extensions.add("readme", readmeExtension)
}
val generateReadme by tasks.registering {
group = "documentation"
description = "Generate a README file if stub is present"
inputs.property("features", readmeExtension.features)
val generateReadme by tasks.registering {
group = "documentation"
description = "Generate a README file if stub is present"
if (readmeExtension.readmeTemplate.exists()) {
inputs.file(readmeExtension.readmeTemplate)
}
inputs.property("features", readmeExtension.features)
readmeExtension.inputFiles.forEach {
if (it.exists()) {
inputs.file(it)
if (readmeExtension.readmeTemplate.exists()) {
inputs.file(readmeExtension.readmeTemplate)
}
}
subprojects {
extensions.findByType<KScienceReadmeExtension>()?.let { subProjectReadmeExtension ->
tasks.findByName("generateReadme")?.let { readmeTask ->
dependsOn(readmeTask)
readmeExtension.inputFiles.forEach {
if (it.exists()) {
inputs.file(it)
}
}
subprojects {
extensions.findByType<KScienceReadmeExtension>()?.let { subProjectReadmeExtension ->
tasks.findByName("generateReadme")?.let { readmeTask ->
dependsOn(readmeTask)
}
inputs.property("features-${name}", subProjectReadmeExtension.features)
}
}
val readmeFile = this@allprojects.file("README.md")
outputs.file(readmeFile)
doLast {
val readmeString = readmeExtension.readmeString()
if (readmeString != null) {
readmeFile.writeText(readmeString)
}
inputs.property("features-${name}", subProjectReadmeExtension.features)
}
}
val readmeFile = this@allprojects.file("README.md")
outputs.file(readmeFile)
tasks.withType<AbstractDokkaTask> {
dependsOn(generateReadme)
}
doLast {
val readmeString = readmeExtension.readmeString()
if (readmeString != null) {
readmeFile.writeText(readmeString)
// Enable API validation for production releases
if (!isInDevelopment && isMature()) {
withKotlin {
extensions.configure<AbiValidationExtension> {
enabled.set(true)
}
}
}
}
tasks.withType<AbstractDokkaTask> {
dependsOn(generateReadme)
}
}
@@ -194,13 +205,7 @@ public open class KScienceProjectPlugin : Plugin<Project> {
}
}
// Disable API validation for snapshots
if (isInDevelopment) {
extensions.findByType<ApiValidationExtension>()?.apply {
validationDisabled = true
logger.warn("API validation is disabled for snapshot or dev version")
}
}
plugins.withType<YarnPlugin> {
rootProject.configure<YarnRootExtension> {

View File

@@ -7,7 +7,6 @@ import freemarker.template.TemplateNotFoundException
import kotlinx.html.TagConsumer
import kotlinx.html.div
import kotlinx.html.stream.createHTML
import kotlinx.validation.ApiValidationExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.findByType
import org.intellij.lang.annotations.Language
@@ -15,13 +14,7 @@ import java.io.File
import java.io.Serializable
import java.io.StringWriter
public enum class Maturity {
PROTOTYPE,
EXPERIMENTAL,
DEVELOPMENT,
STABLE,
DEPRECATED
}
private fun Template.processToString(args: Map<String, Any?>): String {
val writer = StringWriter()
@@ -29,26 +22,13 @@ private fun Template.processToString(args: Map<String, Any?>): String {
return writer.toString()
}
public class KScienceReadmeExtension(private val kscience: KScienceExtension) {
public val project: Project get() = kscience.project
public class KScienceReadmeExtension(public val project: Project) {
public var description: String? = null
get() = field ?: project.description
public var maturity: Maturity = Maturity.EXPERIMENTAL
set(value) {
field = value
val projectName = project.name
if (value == Maturity.EXPERIMENTAL || value == Maturity.PROTOTYPE) {
project.rootProject.run {
plugins.withId("org.jetbrains.kotlinx.binary-compatibility-validator") {
extensions.findByType<ApiValidationExtension>()?.apply {
project.logger.warn("$value project $projectName is excluded from API validation")
ignoredProjects.add(projectName)
}
}
}
}
}
public var maturity: Maturity by kscience::maturity
/**
* If true, use default templates provided by plugin if override is not defined
@@ -86,7 +66,8 @@ public class KScienceReadmeExtension(public val project: Project) {
templateLoader = fmLoader
}
public data class Feature(val id: String, val description: String, val ref: String?, val name: String = id): Serializable
public data class Feature(val id: String, val description: String, val ref: String?, val name: String = id) :
Serializable
public val features: MutableList<Feature> = mutableListOf()
@@ -192,7 +173,11 @@ public class KScienceReadmeExtension(public val project: Project) {
*/
internal fun featuresString(itemPrefix: String = " - ", pathPrefix: String = ""): String = buildString {
features.forEach {
appendLine("$itemPrefix[${it.name}]($pathPrefix${it.ref ?: "#"}) : ${it.description.lines().firstOrNull() ?: ""}")
appendLine(
"$itemPrefix[${it.name}]($pathPrefix${it.ref ?: "#"}) : ${
it.description.lines().firstOrNull() ?: ""
}"
)
}
}

View File

@@ -4,7 +4,9 @@ import org.gradle.api.Project
import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
import org.jetbrains.kotlin.gradle.dsl.KotlinBaseExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import space.kscience.gradle.KScienceExtension
import space.kscience.gradle.KSciencePlugin
@@ -51,4 +53,16 @@ internal fun Project.withKScience(block: KScienceExtension.() -> Unit) {
plugins.withType<KSciencePlugin>().configureEach {
extensions.findByType<KScienceExtension>()?.apply(block)
}
}
/**
* Configures the Kotlin environment in the current project by finding and applying a provided configuration block
* to the KotlinBaseExtension if the KotlinBasePlugin is applied.
*
* @param block The configuration block to apply to the KotlinBaseExtension.
*/
internal fun Project.withKotlin(block: KotlinBaseExtension.() -> Unit) {
plugins.withType<KotlinBasePlugin>().configureEach {
extensions.findByType<KotlinBaseExtension>()?.apply(block)
}
}