From dfcd136dd43104d8023e2e2add903eed295b191b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 8 Feb 2023 01:02:51 +0100 Subject: [PATCH] Replace kotlinx-serialization and kaml by SnakeYAML kaml is very eager for a library when it comes to updating the required Kotlin version. This does not harmonize with the embedded Kotlin runtime in Gradle. Now pure SnakeYAML is used to read the actions file for getting the input defaults. --- gradle/build-logic/build-logic.gradle.kts | 5 +- .../kotlin/net/kautler/dao/action/Branding.kt | 25 ----- .../net/kautler/dao/action/GitHubAction.kt | 33 ++---- .../kotlin/net/kautler/dao/action/Input.kt | 15 +-- .../kotlin/net/kautler/dao/action/Output.kt | 35 ------ .../kautler/dao/action/OutputMapSerializer.kt | 82 -------------- .../kotlin/net/kautler/dao/action/Runs.kt | 106 ------------------ .../kotlin/net/kautler/dao/action/Step.kt | 47 -------- .../net/kautler/dependencies.gradle.kts | 2 - .../main/kotlin/net/kautler/node.gradle.kts | 20 ++-- gradle/libs.versions.toml | 4 +- 11 files changed, 26 insertions(+), 348 deletions(-) delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts index c43ff91b..1dfcb6cf 100644 --- a/gradle/build-logic/build-logic.gradle.kts +++ b/gradle/build-logic/build-logic.gradle.kts @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `kotlin-dsl` - alias(libs.plugins.kotlin.serialization) id(libs.plugins.convention.dependency.updates.report.aggregation.get().pluginId) alias(libs.plugins.dependency.analysis) } @@ -34,9 +33,7 @@ dependencies { implementation(":dependency-updates-report-aggregation") implementation(libs.build.inject) implementation(libs.build.github.api) - implementation(platform(libs.build.kotlinx.serialization.bom)) - implementation(libs.build.kotlinx.serialization.core) - implementation(libs.build.kaml) + implementation(libs.build.snakeyaml) implementation(embeddedKotlin("compiler-embeddable")) } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt deleted file mode 100644 index f5f4c0b4..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020-2023 Björn Kautler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.kautler.dao.action - -import kotlinx.serialization.Serializable - -@Serializable -data class Branding( - val color: String, - val icon: String? = null -) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt index aa65d9e5..59652530 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt @@ -16,29 +16,12 @@ package net.kautler.dao.action -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable -import net.kautler.dao.action.Output.CompositeOutput -import net.kautler.dao.action.Output.NormalOutput - -@ExperimentalSerializationApi -@Serializable -data class GitHubAction( - val name: String, - val author: String? = null, - val description: String, - val inputs: Map? = null, - @Serializable(with = OutputMapSerializer::class) - val outputs: Map? = null, - val runs: Runs, - val branding: Branding? = null -) { - init { - require((runs.using == "composite") || (outputs.orEmpty().values.all { it is NormalOutput })) { - "Non-composite actions must only contain normal outputs" - } - require((runs.using != "composite") || (outputs.orEmpty().values.all { it is CompositeOutput })) { - "Composite actions must only contain composite outputs" - } - } +class GitHubAction { + var name: String? = null + var author: String? = null + var description: String? = null + var inputs: Map? = null + var outputs: Map? = null + var runs: Map? = null + var branding: Map? = null } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt index 8fffb9b7..a36f9514 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt @@ -16,12 +16,9 @@ package net.kautler.dao.action -import kotlinx.serialization.Serializable - -@Serializable -data class Input( - val description: String, - val required: Boolean = false, - val deprecationMessage: String? = null, - val default: String? = null -) +class Input { + var description: String? = null + var required: Boolean = false + var deprecationMessage: String? = null + var default: String? = null +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt deleted file mode 100644 index c4ec5328..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020-2023 Björn Kautler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.kautler.dao.action - -import kotlinx.serialization.Serializable - -@Serializable -sealed class Output { - abstract val description: String - - @Serializable - data class NormalOutput( - override val description: String - ) : Output() - - @Serializable - data class CompositeOutput( - override val description: String, - val value: String - ) : Output() -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt deleted file mode 100644 index 9c92f5a0..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2020-2023 Björn Kautler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.kautler.dao.action - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlScalar -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializer -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.descriptors.SerialKind.CONTEXTUAL -import kotlinx.serialization.descriptors.buildSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import net.kautler.dao.action.Output.CompositeOutput -import net.kautler.dao.action.Output.NormalOutput - -@ExperimentalSerializationApi -@Serializer(forClass = Map::class) -class OutputMapSerializer( - private val keySerializer: KSerializer, - private val valueSerializer: KSerializer -) : KSerializer> { - @InternalSerializationApi - override val descriptor = - buildSerialDescriptor("net.kautler.dao.action.GitHubAction.outputs", CONTEXTUAL) - - override fun deserialize(decoder: Decoder): Map { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val compositeAction = context - .get("runs") - ?.get("using") - ?.content == "composite" - - val valueSerializer = - if (compositeAction) CompositeOutput.serializer() - else NormalOutput.serializer() - - return decoder.decodeSerializableValue(MapSerializer(keySerializer, valueSerializer)) - } - - override fun serialize(encoder: Encoder, value: Map) { - @Suppress("UNCHECKED_CAST") - when (value.values.asSequence().map { it::class }.distinct().count()) { - 0 -> encoder.encodeSerializableValue(MapSerializer(keySerializer, valueSerializer), value) - - 1 -> when (value.values.first()) { - is NormalOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, NormalOutput.serializer()), - value as Map - ) - - is CompositeOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, CompositeOutput.serializer()), - value as Map - ) - } - - else -> error("Output map must not contain normal and composite outputs at the same time") - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt deleted file mode 100644 index bb8d3546..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020-2023 Björn Kautler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.kautler.dao.action - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlScalar -import kotlinx.serialization.EncodeDefault -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.Serializer -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -sealed class Runs { - abstract val using: String - - @Serializable - data class JavaScriptRuns( - override val using: String, - val main: String, - val pre: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val post: String? = null, - @SerialName("post-if") - val postIf: String? = null - ) : Runs() - - @Serializable - data class CompositeRuns( - val steps: List - ) : Runs() { - @ExperimentalSerializationApi - @EncodeDefault - override val using: String = "composite" - } - - @Serializable - data class DockerRuns( - @SerialName("pre-entrypoint") - val preEntrypoint: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val image: String, - val env: Map? = null, - val entrypoint: String? = null, - @SerialName("post-entrypoint") - val postEntrypoint: String? = null, - @SerialName("post-if") - val postIf: String? = null, - val args: List? = null - ) : Runs() { - @ExperimentalSerializationApi - @EncodeDefault - override val using: String = "docker" - } - - @ExperimentalSerializationApi - @Serializer(forClass = Runs::class) - companion object : KSerializer { - override fun deserialize(decoder: Decoder): Runs { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val actionType = context - .get("runs") - ?.get("using") - ?.content - - val valueSerializer = when (actionType) { - "composite" -> CompositeRuns.serializer() - "docker" -> DockerRuns.serializer() - else -> JavaScriptRuns.serializer() - } - - return decoder.decodeSerializableValue(valueSerializer) - } - - override fun serialize(encoder: Encoder, value: Runs) { - when (value) { - is JavaScriptRuns -> encoder.encodeSerializableValue(JavaScriptRuns.serializer(), value) - is CompositeRuns -> encoder.encodeSerializableValue(CompositeRuns.serializer(), value) - is DockerRuns -> encoder.encodeSerializableValue(DockerRuns.serializer(), value) - } - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt deleted file mode 100644 index 4f77a4d1..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020-2023 Björn Kautler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.kautler.dao.action - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class Step( - val run: String? = null, - val shell: String? = null, - val uses: String? = null, - val with: Map? = null, - val name: String? = null, - val id: String? = null, - @SerialName("if") - val condition: String? = null, - val env: Map? = null, - @SerialName("working-directory") - val workingDirectory: String? = null -) { - init { - require((run == null) || (uses == null)) { - "'run' and 'uses' are mutually exclusive" - } - require((run != null) || (uses != null)) { - "one of 'run' or 'uses' is required" - } - require((run == null) || (shell != null)) { - "'shell' is required if 'run' is set" - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts index 3fa56646..9f39109c 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts @@ -62,8 +62,6 @@ tasks.dependencyUpdates { dependsOn(validateGradleWrapperJar) ignoredDependencies { - // Should match the Kotlin version of Gradle as the serialization is used during the build - add(group = "org.jetbrains.kotlin.plugin.serialization", name = "org.jetbrains.kotlin.plugin.serialization.gradle.plugin") // This plugin should always be used without version as it is tightly // tied to the Gradle version that is building the precompiled script plugins add(group = "org.gradle.kotlin.kotlin-dsl", name = "org.gradle.kotlin.kotlin-dsl.gradle.plugin") diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts index e64f1c48..cc908e69 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts @@ -16,16 +16,15 @@ package net.kautler -import com.charleskorn.kaml.Yaml -import kotlinx.serialization.ExperimentalSerializationApi +import java.security.MessageDigest +import kotlin.text.RegexOption.MULTILINE import net.kautler.dao.action.GitHubAction import net.kautler.util.npm import org.gradle.accessors.dm.LibrariesForLibs import org.jetbrains.kotlin.gradle.targets.js.dukat.IntegratedDukatTask import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import java.security.MessageDigest -import kotlin.text.RegexOption.MULTILINE +import org.yaml.snakeyaml.Yaml plugins { kotlin("js") @@ -48,13 +47,13 @@ tasks.withType().configureEach { } } -@ExperimentalSerializationApi val inputDefaultValues by lazy { - Yaml - .default - .decodeFromString(GitHubAction.serializer(), file("action.yml").readText()) + file("action.yml") + .inputStream() + .use { Yaml().loadAs(it, GitHubAction::class.java) } .inputs ?.filterValues { it.default != null } + ?.mapValues { it.value.default!! } ?.filterKeys { !System.getenv().containsKey("INPUT_${it.uppercase()}") } } @@ -65,11 +64,10 @@ tasks.withType().configureEach { environment("RUNNER_TEMP", "$temporaryDir/runner-temp") environment("RUNNER_TOOL_CACHE", toolCacheDir) - @OptIn(ExperimentalSerializationApi::class) - inputDefaultValues?.forEach { (name, input) -> + inputDefaultValues?.forEach { (name, default) -> environment( "INPUT_${name.uppercase()}", - if (name == "use-cache") "false" else input.default!! + if (name == "use-cache") "false" else default ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 61064c63..07baeead 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,10 +22,10 @@ build-gradle-plugin-refresh-versions = "0.51.0" build-gradle-plugin-release = "2.8.1" build-gradle-plugin-versions = "0.45.0" build-inject = "1" -build-kaml = "0.51.0" build-kotlin = "1.8.10" build-kotlinx-serialization = "1.4.1" build-node = "16.18.1" +build-snakeyaml = "1.33" build-vercel-ncc = "0.36.1" kotlin = "1.8.10" kotlin-wrappers = "1.0.0-pre.498" @@ -38,10 +38,10 @@ workflows-kotlin = "1.8.10" [libraries] build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } build-inject = { module = "javax.inject:javax.inject", version.ref = "build-inject" } -build-kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "build-kaml" } build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "build-kotlinx-serialization" } build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } build-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } +build-snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "build-snakeyaml" } build-vercel-ncc = { module = "vercel:ncc", version.ref = "build-vercel-ncc" } kotlin-wrapper-actions-toolkit = { module = "org.jetbrains.kotlin-wrappers:kotlin-actions-toolkit" } kotlin-wrapper-js = { module = "org.jetbrains.kotlin-wrappers:kotlin-js" }