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" }