From f2e6c05557be0a60fedb5150b632251eda51e5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 6 Sep 2024 16:53:50 +0200 Subject: [PATCH] feat(abg)!: replace data class perks by code generation in bindings --- .github/workflows/bindings-server.main.kts | 10 + .github/workflows/bindings-server.yaml | 12 +- ...ng-jit-bindings-v1.main.do-not-compile.kts | 2 +- ...ng-jit-bindings-v2.main.do-not-compile.kts | 33 + ...uming-jit-bindings.main.do-not-compile.kts | 2 +- .../api/action-binding-generator.api | 1 + action-binding-generator/build.gradle.kts | 2 + .../generation/Generation.kt | 367 +++++++-- .../versioning/BindingVersion.kt | 1 + .../workflows/actionbindinggenerator/Utils.kt | 71 ++ ...=> ActionWithAllTypesOfInputsBindingV1.kt} | 58 +- ...nWithAllTypesOfInputsBindingV1_Untyped.kt} | 10 +- .../ActionWithAllTypesOfInputsBindingV2.kt | 554 ++++++++++++++ ...onWithAllTypesOfInputsBindingV2_Untyped.kt | 295 +++++++ .../ActionWithAllTypesOfInputsTest.kt | 409 ++++++---- ...thDeprecatedInputAndNameClashBindingV1.kt} | 9 +- ...ithDeprecatedInputAndNameClashBindingV2.kt | 136 ++++ ...=> ActionWithFancyCharsInDocsBindingV1.kt} | 8 +- .../ActionWithFancyCharsInDocsBindingV2.kt | 161 ++++ ...> ActionWithInputsSharingTypeBindingV1.kt} | 24 +- .../ActionWithInputsSharingTypeBindingV2.kt | 197 +++++ ...puts.kt => ActionWithNoInputsBindingV1.kt} | 7 +- .../ActionWithNoInputsBindingV2.kt | 96 +++ ...> ActionWithNoTypingsBindingV1_Untyped.kt} | 7 +- .../ActionWithNoTypingsBindingV2_Untyped.kt | 138 ++++ ...tputs.kt => ActionWithOutputsBindingV1.kt} | 8 +- .../ActionWithOutputsBindingV2.kt | 148 ++++ .../ActionWithOutputsTest.kt | 39 +- ...kt => ActionWithPartlyTypingsBindingV1.kt} | 8 +- ...tionWithPartlyTypingsBindingV1_Untyped.kt} | 10 +- .../ActionWithPartlyTypingsBindingV2.kt | 150 ++++ ...ctionWithPartlyTypingsBindingV2_Untyped.kt | 154 ++++ ... ActionWithSomeOptionalInputsBindingV1.kt} | 8 +- .../ActionWithSomeOptionalInputsBindingV2.kt | 254 ++++++ .../ActionWithSomeOptionalInputsTest.kt | 36 +- ...ctionWithRequiredStringInputsBindingV1.kt} | 9 +- ...ActionWithRequiredStringInputsBindingV2.kt | 182 +++++ ...impleActionWithRequiredStringInputsTest.kt | 36 +- .../generation/GenerationTest.kt | 721 +++++++++--------- docs/user-guide/using-actions.md | 86 +++ mkdocs.yml | 5 + 41 files changed, 3800 insertions(+), 664 deletions(-) create mode 100755 .github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithAllTypesOfInputs.kt => ActionWithAllTypesOfInputsBindingV1.kt} (85%) rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithAllTypesOfInputs_Untyped.kt => ActionWithAllTypesOfInputsBindingV1_Untyped.kt} (95%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2.kt create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2_Untyped.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithDeprecatedInputAndNameClash.kt => ActionWithDeprecatedInputAndNameClashBindingV1.kt} (89%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithFancyCharsInDocs.kt => ActionWithFancyCharsInDocsBindingV1.kt} (95%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithInputsSharingType.kt => ActionWithInputsSharingTypeBindingV1.kt} (85%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithNoInputs.kt => ActionWithNoInputsBindingV1.kt} (93%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithNoTypings_Untyped.kt => ActionWithNoTypingsBindingV1_Untyped.kt} (96%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV2_Untyped.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithOutputs.kt => ActionWithOutputsBindingV1.kt} (93%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithPartlyTypings.kt => ActionWithPartlyTypingsBindingV1.kt} (95%) rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithPartlyTypings_Untyped.kt => ActionWithPartlyTypingsBindingV1_Untyped.kt} (94%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2.kt create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2_Untyped.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{ActionWithSomeOptionalInputs.kt => ActionWithSomeOptionalInputsBindingV1.kt} (97%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV2.kt rename action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/{SimpleActionWithRequiredStringInputs.kt => SimpleActionWithRequiredStringInputsBindingV1.kt} (92%) create mode 100644 action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV2.kt diff --git a/.github/workflows/bindings-server.main.kts b/.github/workflows/bindings-server.main.kts index ee74cf5037..ce3fe70891 100755 --- a/.github/workflows/bindings-server.main.kts +++ b/.github/workflows/bindings-server.main.kts @@ -101,6 +101,16 @@ workflow( cleanMavenLocal() + run( + name = "Execute the script using the bindings from the server with v2 route", + command = """ + mv .github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts .github/workflows/test-script-consuming-jit-bindings-v2.main.kts + .github/workflows/test-script-consuming-jit-bindings-v2.main.kts + """.trimIndent(), + ) + + cleanMavenLocal() + run( name = "Execute the script using bindings but without dependency on library", command = """ diff --git a/.github/workflows/bindings-server.yaml b/.github/workflows/bindings-server.yaml index 003494ad4b..9aca42a84a 100644 --- a/.github/workflows/bindings-server.yaml +++ b/.github/workflows/bindings-server.yaml @@ -65,14 +65,22 @@ jobs: name: 'Clean Maven Local to fetch required POMs again' run: 'rm -rf ~/.m2/repository/' - id: 'step-9' + name: 'Execute the script using the bindings from the server with v2 route' + run: |- + mv .github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts .github/workflows/test-script-consuming-jit-bindings-v2.main.kts + .github/workflows/test-script-consuming-jit-bindings-v2.main.kts + - id: 'step-10' + name: 'Clean Maven Local to fetch required POMs again' + run: 'rm -rf ~/.m2/repository/' + - id: 'step-11' name: 'Execute the script using bindings but without dependency on library' run: |- mv .github/workflows/test-served-bindings-depend-on-library.main.do-not-compile.kts .github/workflows/test-served-bindings-depend-on-library.main.kts .github/workflows/test-served-bindings-depend-on-library.main.kts - - id: 'step-10' + - id: 'step-12' name: 'Fetch maven-metadata.xml for top-level action' run: 'curl --fail http://localhost:8080/actions/checkout/maven-metadata.xml | grep ''v4''' - - id: 'step-11' + - id: 'step-13' name: 'Fetch maven-metadata.xml for nested action' run: 'curl --fail http://localhost:8080/actions/cache__save/maven-metadata.xml | grep ''v4''' deploy: diff --git a/.github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts b/.github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts index 0104863de3..6a03dcc061 100755 --- a/.github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts +++ b/.github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts @@ -1,6 +1,6 @@ #!/usr/bin/env kotlin @file:Repository("https://repo.maven.apache.org/maven2/") -@file:DependsOn("io.github.typesafegithub:github-workflows-kt:1.13.0") +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.0.0") @file:Repository("http://localhost:8080/v1") diff --git a/.github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts b/.github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts new file mode 100755 index 0000000000..eab3179228 --- /dev/null +++ b/.github/workflows/test-script-consuming-jit-bindings-v2.main.do-not-compile.kts @@ -0,0 +1,33 @@ +#!/usr/bin/env kotlin +@file:Repository("https://repo.maven.apache.org/maven2/") +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.0.0") + +@file:Repository("http://localhost:8080/v2") + +// Regular, top-level action. +@file:DependsOn("actions:checkout:v4") + +// Nested action. +@file:DependsOn("gradle:actions__setup-gradle:v3") + +// Using specific version. +@file:DependsOn("actions:cache:v3.3.3") + +// Always untyped action. +@file:DependsOn("typesafegithub:always-untyped-action-for-tests:v1") + +import io.github.typesafegithub.workflows.actions.actions.Cache +import io.github.typesafegithub.workflows.actions.actions.Checkout +import io.github.typesafegithub.workflows.actions.actions.Checkout_Untyped +import io.github.typesafegithub.workflows.actions.gradle.ActionsSetupGradle +import io.github.typesafegithub.workflows.actions.typesafegithub.AlwaysUntypedActionForTests_Untyped + +println(Checkout_Untyped(fetchTags_Untyped = "false")) +println(Checkout(fetchTags = false)) +println(Checkout(fetchTags_Untyped = "false")) +println(AlwaysUntypedActionForTests_Untyped(foobar_Untyped = "baz")) +println(ActionsSetupGradle()) +println(Cache(path = listOf("some-path"), key = "some-key")) + +// Ensure that 'copy(...)' method is exposed. +Checkout(fetchTags = false).copy(fetchTags = true) diff --git a/.github/workflows/test-script-consuming-jit-bindings.main.do-not-compile.kts b/.github/workflows/test-script-consuming-jit-bindings.main.do-not-compile.kts index 92fe969476..8e7cd6113e 100755 --- a/.github/workflows/test-script-consuming-jit-bindings.main.do-not-compile.kts +++ b/.github/workflows/test-script-consuming-jit-bindings.main.do-not-compile.kts @@ -1,6 +1,6 @@ #!/usr/bin/env kotlin @file:Repository("https://repo.maven.apache.org/maven2/") -@file:DependsOn("io.github.typesafegithub:github-workflows-kt:1.13.0") +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.0.0") @file:Repository("http://localhost:8080") diff --git a/action-binding-generator/api/action-binding-generator.api b/action-binding-generator/api/action-binding-generator.api index 2a44cd72a5..e1b8a78064 100644 --- a/action-binding-generator/api/action-binding-generator.api +++ b/action-binding-generator/api/action-binding-generator.api @@ -181,6 +181,7 @@ public abstract interface class io/github/typesafegithub/workflows/actionbinding public final class io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion : java/lang/Enum { public static final field V1 Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion; + public static final field V2 Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion; public static fun getEntries ()Lkotlin/enums/EnumEntries; public final fun getLibraryVersion ()Ljava/lang/String; public final fun isDeprecated ()Z diff --git a/action-binding-generator/build.gradle.kts b/action-binding-generator/build.gradle.kts index c0123973be..b5ad658ab4 100644 --- a/action-binding-generator/build.gradle.kts +++ b/action-binding-generator/build.gradle.kts @@ -16,6 +16,8 @@ dependencies { implementation("com.charleskorn.kaml:kaml:0.61.0") implementation(projects.sharedInternal) + testImplementation("io.kotest:kotest-framework-datatest") + testImplementation(kotlin("reflect")) testImplementation(projects.githubWorkflowsKt) } diff --git a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/Generation.kt b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/Generation.kt index ebb0fa2794..70b37a00f3 100644 --- a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/Generation.kt +++ b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/Generation.kt @@ -6,6 +6,9 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.KModifier.OVERRIDE +import com.squareup.kotlinpoet.KModifier.PRIVATE +import com.squareup.kotlinpoet.KModifier.VARARG import com.squareup.kotlinpoet.MemberName import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy @@ -15,11 +18,14 @@ import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.asClassName import com.squareup.kotlinpoet.asTypeName import com.squareup.kotlinpoet.buildCodeBlock +import com.squareup.kotlinpoet.joinToCode import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource +import io.github.typesafegithub.workflows.actionbindinggenerator.domain.prettyPrint import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_INPUTS import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_VERSION +import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Types.nullableAny import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Input import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Metadata import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.fetchMetadata @@ -35,6 +41,8 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toCamelCa import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toKotlinPackageName import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V1 +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V2 +import java.util.Objects public data class ActionBinding( val kotlinCode: String, @@ -46,6 +54,7 @@ public data class ActionBinding( private object Types { val mapStringString = Map::class.asTypeName().parameterizedBy(String::class.asTypeName(), String::class.asTypeName()) + val nullableAny = Any::class.asTypeName().copy(nullable = true) val nullableString = String::class.asTypeName().copy(nullable = true) val mapToList = MemberName("kotlin.collections", "toList") val listToArray = MemberName("kotlin.collections", "toTypedArray") @@ -132,69 +141,97 @@ private fun generateActionBindingSourceCode( untypedClass: Boolean = false, replaceWith: CodeBlock? = null, ): String { + val packageName = "io.github.typesafegithub.workflows.actions.${coords.owner.toKotlinPackageName()}" val fileSpec = FileSpec - .builder( - "io.github.typesafegithub.workflows.actions.${coords.owner.toKotlinPackageName()}", - className, - ).addFileComment( + .builder(packageName, className) + .addFileComment( """ This file was generated using action-binding-generator. Don't change it by hand, otherwise your changes will be overwritten with the next binding code regeneration. See https://github.com/typesafegithub/github-workflows-kt for more info. """.trimIndent(), - ).addType(generateActionClass(metadata, coords, bindingVersion, inputTypings, className, untypedClass, replaceWith)) - .addSuppressAnnotation(metadata) - .indent(" ") + ).addType( + generateActionClass( + metadata, + coords, + bindingVersion, + inputTypings, + packageName, + className, + untypedClass, + replaceWith, + ), + ).addSuppressAnnotation( + bindingVersion = bindingVersion, + classIsDeprecated = replaceWith != null, + metadata = metadata, + ).indent(" ") .build() return buildString { fileSpec.writeTo(this) } } -private fun FileSpec.Builder.addSuppressAnnotation(metadata: Metadata) = - apply { - val isDeprecatedInputUsed = metadata.inputs.values.any { it.deprecationMessage.isNullOrBlank().not() } - - addAnnotation( - AnnotationSpec - .builder(Suppress::class.asClassName()) - .addMember(CodeBlock.of("%S", "DataClassPrivateConstructor")) - .addMember(CodeBlock.of("%S", "UNUSED_PARAMETER")) - .apply { - if (isDeprecatedInputUsed) { - addMember(CodeBlock.of("%S", "DEPRECATION")) - } - }.build(), - ) +private fun FileSpec.Builder.addSuppressAnnotation( + bindingVersion: BindingVersion, + classIsDeprecated: Boolean, + metadata: Metadata, +): FileSpec.Builder { + val suppress = AnnotationSpec.builder(Suppress::class.asClassName()) + if (bindingVersion <= V1) { + suppress.addMember(CodeBlock.of("%S", "DataClassPrivateConstructor")) + } + suppress.addMember(CodeBlock.of("%S", "UNUSED_PARAMETER")) + val isDeprecatedInputUsed = metadata.inputs.values.any { it.deprecationMessage.isNullOrBlank().not() } + if (bindingVersion.isDeprecated || (bindingVersion >= V2 && classIsDeprecated) || isDeprecatedInputUsed) { + suppress.addMember(CodeBlock.of("%S", "DEPRECATION")) } + addAnnotation(suppress.build()) + return this +} private fun generateActionClass( metadata: Metadata, coords: ActionCoords, bindingVersion: BindingVersion, inputTypings: Map, + packageName: String, className: String, untypedClass: Boolean, replaceWith: CodeBlock?, -): TypeSpec = - TypeSpec +): TypeSpec { + val commonConstructorParameters = + metadata.buildCommonConstructorParameters(inputTypings, coords, className, untypedClass) + return TypeSpec .classBuilder(className) - .addModifiers(KModifier.DATA) + .addDataModifier(bindingVersion) .addKdocIfNotEmpty(actionKdoc(metadata, coords, untypedClass)) .deprecateBindingVersion(bindingVersion) .replaceWith(bindingVersion, replaceWith) - .addClassConstructorAnnotation() + .addClassConstructorAnnotation(bindingVersion) .inheritsFromRegularAction(coords, metadata, className) - .primaryConstructor(metadata.primaryConstructor(inputTypings, coords, className, untypedClass)) + .primaryConstructor(buildPrimaryConstructor(bindingVersion, commonConstructorParameters)) .properties(metadata, coords, inputTypings, className, untypedClass) - .addInitializerBlock(metadata, bindingVersion, inputTypings, untypedClass) - .addFunction(metadata.secondaryConstructor(inputTypings, coords, className, untypedClass)) + .addInitializerBlock(metadata, bindingVersion, coords, inputTypings, untypedClass) + .addSecondaryConstructor(bindingVersion, metadata, inputTypings, commonConstructorParameters, untypedClass) .addFunction(metadata.buildToYamlArgumentsFunction(inputTypings, untypedClass)) + .addEqualsFunction(bindingVersion, className, commonConstructorParameters) + .addHashCodeFunction(bindingVersion, commonConstructorParameters) + .addToStringFunction(bindingVersion, className, commonConstructorParameters) + .addCopyFunction(bindingVersion, packageName, className, commonConstructorParameters) .addCustomTypes(inputTypings, coords, className) .addOutputClassIfNecessary(metadata) .addBuildOutputObjectFunctionIfNecessary(metadata) .build() +} + +private fun TypeSpec.Builder.addDataModifier(bindingVersion: BindingVersion): TypeSpec.Builder { + if (bindingVersion <= V1) { + addModifiers(KModifier.DATA) + } + return this +} private fun TypeSpec.Builder.addCustomTypes( typings: Map, @@ -308,7 +345,7 @@ private fun TypeSpec.Builder.addBuildOutputObjectFunctionIfNecessary(metadata: M FunSpec .builder("buildOutputObject") .returns(if (metadata.outputs.isEmpty()) OutputsBase else ClassName("", "Outputs")) - .addModifiers(KModifier.OVERRIDE) + .addModifiers(OVERRIDE) .addParameter("stepId", String::class) .addCode(CodeBlock.of("return Outputs(stepId)")) .build(), @@ -334,7 +371,7 @@ private fun Metadata.buildToYamlArgumentsFunction( untypedClass: Boolean, ) = FunSpec .builder("toYamlArguments") - .addModifiers(KModifier.OVERRIDE) + .addModifiers(OVERRIDE) .returns(LinkedHashMap::class.parameterizedBy(String::class, String::class)) .addAnnotation( AnnotationSpec @@ -411,12 +448,14 @@ private fun TypeSpec.Builder.replaceWith( return this } -private fun TypeSpec.Builder.addClassConstructorAnnotation(): TypeSpec.Builder { - addAnnotation( - AnnotationSpec - .builder(ExposedCopyVisibility::class.asClassName()) - .build(), - ) +private fun TypeSpec.Builder.addClassConstructorAnnotation(bindingVersion: BindingVersion): TypeSpec.Builder { + if (bindingVersion <= V1) { + addAnnotation( + AnnotationSpec + .builder(ExposedCopyVisibility::class.asClassName()) + .build(), + ) + } return this } @@ -445,22 +484,42 @@ private fun TypeSpec.Builder.inheritsFromRegularAction( .addSuperclassConstructorParameter("_customVersion ?: %S", coords.version) } -private fun Metadata.primaryConstructor( +private fun buildPrimaryConstructor( + bindingVersion: BindingVersion, + commonConstructorParameters: Iterable, +): FunSpec { + val constructor = FunSpec.constructorBuilder() + if (bindingVersion <= V1) { + constructor.addModifiers(PRIVATE) + } + if (bindingVersion >= V2) { + constructor + .addParameter( + ParameterSpec + .builder("pleaseUseNamedArguments", Unit::class) + .addModifiers(VARARG) + .build(), + ) + } + return constructor.addParameters(commonConstructorParameters).build() +} + +private fun TypeSpec.Builder.addSecondaryConstructor( + bindingVersion: BindingVersion, + metadata: Metadata, inputTypings: Map, - coords: ActionCoords, - className: String, + commonConstructorParameters: Iterable, untypedClass: Boolean, -): FunSpec = - FunSpec - .constructorBuilder() - .addModifiers(KModifier.PRIVATE) - .addParameters(buildCommonConstructorParameters(inputTypings, coords, className, untypedClass)) - .build() +): TypeSpec.Builder { + if (bindingVersion <= V1) { + addFunction(metadata.buildSecondaryConstructor(inputTypings, commonConstructorParameters, untypedClass)) + } + return this +} -private fun Metadata.secondaryConstructor( +private fun Metadata.buildSecondaryConstructor( inputTypings: Map, - coords: ActionCoords, - className: String, + commonConstructorParameters: Iterable, untypedClass: Boolean, ): FunSpec = FunSpec @@ -468,9 +527,9 @@ private fun Metadata.secondaryConstructor( .addParameter( ParameterSpec .builder("pleaseUseNamedArguments", Unit::class) - .addModifiers(KModifier.VARARG) + .addModifiers(VARARG) .build(), - ).addParameters(buildCommonConstructorParameters(inputTypings, coords, className, untypedClass)) + ).addParameters(commonConstructorParameters) .callThisConstructor( inputs .keys @@ -547,6 +606,203 @@ private fun Metadata.buildCommonConstructorParameters( ).build(), ) +private fun TypeSpec.Builder.addEqualsFunction( + bindingVersion: BindingVersion, + className: String, + commonConstructorParameters: Iterable, +): TypeSpec.Builder { + if (bindingVersion >= V2) { + addFunction(buildEqualsFunction(className, commonConstructorParameters)) + } + return this +} + +private fun buildEqualsFunction( + className: String, + commonConstructorParameters: Iterable, +) = FunSpec + .builder("equals") + .addModifiers(OVERRIDE) + .addParameter(ParameterSpec.builder("other", nullableAny).build()) + .returns(Boolean::class) + .addCode( + buildCodeBlock { + addStatement("if (this === other) return true") + addStatement("if (javaClass != other?.javaClass) return false") + addStatement("other as %N", className) + + val propertyNames = commonConstructorParameters.map { it.name } + when (propertyNames.size) { + 0 -> addStatement("return true") + 1 -> addStatement("return %1N == other.%1N", propertyNames.first()) + else -> { + add("return %1N == other.%1N &&\n", propertyNames.first()) + add( + propertyNames.drop(1).joinToCode( + separator = " &&\n", + ) { + buildCodeBlock { + indent() + add("%1N == other.%1N", it) + unindent() + } + }, + ) + } + } + }, + ).build() + +private fun TypeSpec.Builder.addHashCodeFunction( + bindingVersion: BindingVersion, + commonConstructorParameters: Iterable, +) = apply { + if (bindingVersion >= V2) { + addFunction(buildHashCodeFunction(commonConstructorParameters)) + } +} + +private fun buildHashCodeFunction(commonConstructorParameters: Iterable) = + FunSpec + .builder("hashCode") + .addModifiers(OVERRIDE) + .returns(Int::class) + .addCode( + buildCodeBlock { + val propertyNames = commonConstructorParameters.map { it.name } + when (propertyNames.size) { + 0 -> addStatement("return 0") + 1 -> addStatement("return %T.hash(%N)", Objects::class, propertyNames.first()) + else -> { + add("return %T.hash(\n", Objects::class) + add( + propertyNames.joinToCode( + separator = ",\n", + suffix = ",\n)", + ) { + buildCodeBlock { + indent() + add("%N", it) + unindent() + } + }, + ) + } + } + }, + ).build() + +private fun TypeSpec.Builder.addToStringFunction( + bindingVersion: BindingVersion, + className: String, + commonConstructorParameters: Iterable, +): TypeSpec.Builder { + if (bindingVersion >= V2) { + addFunction(buildToStringFunction(className, commonConstructorParameters)) + } + return this +} + +private fun buildToStringFunction( + className: String, + commonConstructorParameters: Iterable, +) = FunSpec + .builder("toString") + .addModifiers(OVERRIDE) + .returns(String::class) + .addCode( + buildCodeBlock { + val propertyNames = commonConstructorParameters.map { it.name } + when (propertyNames.size) { + 0 -> addStatement("return %S", "$className()") + + 1 -> + addStatement( + "return %P", + buildCodeBlock { + add("%1L(%2L=$%2N)", className, propertyNames.first()) + }, + ) + + else -> { + beginControlFlow("return buildString") + addStatement("append(%S)", "$className(") + propertyNames.dropLast(1).forEach { + addStatement( + "append(%P)", + buildCodeBlock { + add("%1L=$%1N", it) + }, + ) + addStatement("append(%S)", ", ") + } + addStatement( + "append(%P)", + buildCodeBlock { + add("%1L=$%1N", propertyNames.last()) + }, + ) + addStatement("append(%S)", ")") + endControlFlow() + } + } + }, + ).build() + +private fun TypeSpec.Builder.addCopyFunction( + bindingVersion: BindingVersion, + packageName: String, + className: String, + commonConstructorParameters: Iterable, +): TypeSpec.Builder { + if (bindingVersion >= V2) { + addFunction(buildCopyFunction(packageName, className, commonConstructorParameters)) + } + return this +} + +private fun buildCopyFunction( + packageName: String, + className: String, + commonConstructorParameters: Iterable, +) = FunSpec + .builder("copy") + .returns(ClassName(packageName, className)) + .addParameter( + ParameterSpec + .builder("pleaseUseNamedArguments", Unit::class) + .addModifiers(VARARG) + .build(), + ).addParameters( + commonConstructorParameters + .map { it.toBuilder().defaultValue("this.%N", it.name).build() }, + ).addCode( + buildCodeBlock { + val propertyNames = commonConstructorParameters.map { it.name } + when (propertyNames.size) { + 0 -> addStatement("return %N()", className) + + 1 -> addStatement("return %1N(%2N = %2N)", className, propertyNames.first()) + + else -> { + add("return %1N(\n", className) + add( + propertyNames.joinToCode( + separator = "", + suffix = ")", + ) { + buildCodeBlock { + indent() + add("%1N = %1N,\n", it) + unindent() + } + }, + ) + } + } + }, + ).build() + private fun ParameterSpec.Builder.defaultValueIfNullable( input: Input, untypedClass: Boolean, @@ -561,6 +817,7 @@ private fun ParameterSpec.Builder.defaultValueIfNullable( private fun TypeSpec.Builder.addInitializerBlock( metadata: Metadata, bindingVersion: BindingVersion, + coords: ActionCoords, inputTypings: Map, untypedClass: Boolean, ): TypeSpec.Builder { @@ -578,7 +835,7 @@ private fun TypeSpec.Builder.addInitializerBlock( addStatement( "println(%S)", """ - WARNING: The used binding version $bindingVersion is deprecated! First stable version is $firstStableVersion. + WARNING: The used binding version $bindingVersion for ${coords.prettyPrint} is deprecated! First stable version is $firstStableVersion. """.trimIndent(), ) beginControlFlow("""if (System.getenv("GITHUB_ACTIONS").toBoolean())""") @@ -586,7 +843,7 @@ private fun TypeSpec.Builder.addInitializerBlock( "println(%S)", """ - ::warning title=Deprecated Binding Version Used::The used binding version $bindingVersion is deprecated! First stable version is $firstStableVersion. + ::warning title=Deprecated Binding Version Used::The used binding version $bindingVersion for ${coords.prettyPrint} is deprecated! First stable version is $firstStableVersion. """.trimIndent(), ) endControlFlow() @@ -597,7 +854,7 @@ private fun TypeSpec.Builder.addInitializerBlock( addStatement( "println(%S)", """ - WARNING: The used binding version $bindingVersion is experimental! Last stable version is $lastStableVersion. + WARNING: The used binding version $bindingVersion for ${coords.prettyPrint} is experimental! Last stable version is $lastStableVersion. """.trimIndent(), ) beginControlFlow("""if (System.getenv("GITHUB_ACTIONS").toBoolean())""") @@ -605,7 +862,7 @@ private fun TypeSpec.Builder.addInitializerBlock( "println(%S)", """ - ::warning title=Experimental Binding Version Used::The used binding version $bindingVersion is experimental! Last stable version is $lastStableVersion. + ::warning title=Experimental Binding Version Used::The used binding version $bindingVersion for ${coords.prettyPrint} is experimental! Last stable version is $lastStableVersion. """.trimIndent(), ) endControlFlow() diff --git a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion.kt b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion.kt index e109473b94..3a144065ea 100644 --- a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion.kt +++ b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion.kt @@ -6,6 +6,7 @@ public enum class BindingVersion( public val libraryVersion: String, ) { V1(isExperimental = false, libraryVersion = "3.0.0"), + V2(libraryVersion = "3.0.0"), ; override fun toString(): String = super.toString().lowercase() diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/Utils.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/Utils.kt index cfe5d5311b..662b75f80a 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/Utils.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/Utils.kt @@ -1,8 +1,14 @@ package io.github.typesafegithub.workflows.actionbindinggenerator import io.github.typesafegithub.workflows.actionbindinggenerator.generation.ActionBinding +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion +import io.github.typesafegithub.workflows.domain.actions.Action +import io.kotest.common.mapError +import io.kotest.core.spec.style.scopes.ContainerScope +import io.kotest.datatest.withData import io.kotest.matchers.Matcher.Companion.failure import io.kotest.matchers.shouldBe +import java.lang.reflect.InvocationTargetException import java.nio.file.Paths fun List.shouldContainAndMatchFile(path: String) { @@ -36,3 +42,68 @@ fun List.shouldContainAndMatchFile(path: String) { } private fun String.removeWindowsNewLines(): String = replace("\r\n", "\n") + +fun constructAction( + owner: String, + classBaseName: String, + bindingVersion: BindingVersion, + arguments: Map = emptyMap(), +): Action<*> { + val constructor = + Class + .forName("io.github.typesafegithub.workflows.actions.$owner.${classBaseName}Binding${bindingVersion.name}") + .let { + @Suppress("UNCHECKED_CAST") + it as Class> + }.kotlin + .constructors + .first() + return runCatching { + constructor.callBy( + arguments.mapKeys { (key, _) -> + constructor.parameters.first { it.name == key } + }, + ) + }.mapError { + if (it is InvocationTargetException) it.targetException else it + }.getOrThrow() +} + +suspend fun ContainerScope.withBindingVersions( + bindingVersions: Iterable, + test: suspend ContainerScope.(BindingVersion) -> Unit, +) = withData( + nameFn = { "binding version $it" }, + ts = bindingVersions, + test = test, +) + +suspend fun ContainerScope.withAllBindingVersions(test: suspend ContainerScope.(BindingVersion) -> Unit) = + withBindingVersions( + bindingVersions = BindingVersion.entries, + test = test, + ) + +suspend fun ContainerScope.withBindingVersions( + bindingVersions: OpenEndRange, + test: suspend ContainerScope.(BindingVersion) -> Unit, +) = withBindingVersions( + bindingVersions = BindingVersion.entries.filter { it in bindingVersions }, + test = test, +) + +suspend fun ContainerScope.withBindingVersions( + bindingVersions: ClosedRange, + test: suspend ContainerScope.(BindingVersion) -> Unit, +) = withBindingVersions( + bindingVersions = BindingVersion.entries.filter { it in bindingVersions }, + test = test, +) + +suspend fun ContainerScope.withBindingVersionsFrom( + bindingVersion: BindingVersion, + test: suspend ContainerScope.(BindingVersion) -> Unit, +) = withBindingVersions( + bindingVersions = bindingVersion..BindingVersion.entries.last(), + test = test, +) diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1.kt similarity index 85% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1.kt index 267a846500..10ca833319 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1.kt @@ -28,7 +28,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs) + * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs-binding-v1) * * @param fooBar <required> Short description * @param fooBar_Untyped <required> Short description @@ -60,7 +60,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithAllTypesOfInputs private constructor( +public data class ActionWithAllTypesOfInputsBindingV1 private constructor( /** * <required> Short description */ @@ -104,7 +104,7 @@ public data class ActionWithAllTypesOfInputs private constructor( /** * <required> Enumeration */ - public val finBin: ActionWithAllTypesOfInputs.Bin? = null, + public val finBin: ActionWithAllTypesOfInputsBindingV1.Bin? = null, /** * <required> Enumeration */ @@ -112,7 +112,7 @@ public data class ActionWithAllTypesOfInputs private constructor( /** * <required> Integer with special value */ - public val gooZen: ActionWithAllTypesOfInputs.Zen? = null, + public val gooZen: ActionWithAllTypesOfInputsBindingV1.Zen? = null, /** * <required> Integer with special value */ @@ -120,7 +120,7 @@ public data class ActionWithAllTypesOfInputs private constructor( /** * <required> Enum with custom naming */ - public val bahEnum: ActionWithAllTypesOfInputs.BahEnum? = null, + public val bahEnum: ActionWithAllTypesOfInputsBindingV1.BahEnum? = null, /** * <required> Enum with custom naming */ @@ -144,7 +144,7 @@ public data class ActionWithAllTypesOfInputs private constructor( /** * List of enums */ - public val listEnums: List? = null, + public val listEnums: List? = null, /** * List of enums */ @@ -152,7 +152,7 @@ public data class ActionWithAllTypesOfInputs private constructor( /** * List of integer with special values */ - public val listIntSpecial: List? = null, + public val listIntSpecial: List? = null, /** * List of integer with special values */ @@ -166,8 +166,8 @@ public data class ActionWithAllTypesOfInputs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", - "action-with-all-types-of-inputs", _customVersion ?: "v3") { +) : RegularAction("john-smith", + "action-with-all-types-of-inputs-binding-v1", _customVersion ?: "v3") { init { require(!((fooBar != null) && (fooBar_Untyped != null))) { "Only fooBar or fooBar_Untyped must be set, but not both" @@ -251,19 +251,19 @@ public data class ActionWithAllTypesOfInputs private constructor( intPint_Untyped: String? = null, floPint: Float? = null, floPint_Untyped: String? = null, - finBin: ActionWithAllTypesOfInputs.Bin? = null, + finBin: ActionWithAllTypesOfInputsBindingV1.Bin? = null, finBin_Untyped: String? = null, - gooZen: ActionWithAllTypesOfInputs.Zen? = null, + gooZen: ActionWithAllTypesOfInputsBindingV1.Zen? = null, gooZen_Untyped: String? = null, - bahEnum: ActionWithAllTypesOfInputs.BahEnum? = null, + bahEnum: ActionWithAllTypesOfInputsBindingV1.BahEnum? = null, bahEnum_Untyped: String? = null, listStrings: List? = null, listStrings_Untyped: String? = null, listInts: List? = null, listInts_Untyped: String? = null, - listEnums: List? = null, + listEnums: List? = null, listEnums_Untyped: String? = null, - listIntSpecial: List? = null, + listIntSpecial: List? = null, listIntSpecial_Untyped: String? = null, _customInputs: Map = mapOf(), _customVersion: String? = null, @@ -314,15 +314,15 @@ public data class ActionWithAllTypesOfInputs private constructor( public sealed class Bin( public val stringValue: String, ) { - public object Foo : ActionWithAllTypesOfInputs.Bin("foo") + public object Foo : ActionWithAllTypesOfInputsBindingV1.Bin("foo") - public object BooBar : ActionWithAllTypesOfInputs.Bin("boo-bar") + public object BooBar : ActionWithAllTypesOfInputsBindingV1.Bin("boo-bar") - public object Baz123 : ActionWithAllTypesOfInputs.Bin("baz123") + public object Baz123 : ActionWithAllTypesOfInputsBindingV1.Bin("baz123") public class Custom( customStringValue: String, - ) : ActionWithAllTypesOfInputs.Bin(customStringValue) + ) : ActionWithAllTypesOfInputsBindingV1.Bin(customStringValue) } public sealed class Zen( @@ -330,35 +330,35 @@ public data class ActionWithAllTypesOfInputs private constructor( ) { public class Value( requestedValue: Int, - ) : ActionWithAllTypesOfInputs.Zen(requestedValue) + ) : ActionWithAllTypesOfInputsBindingV1.Zen(requestedValue) - public object Special1 : ActionWithAllTypesOfInputs.Zen(3) + public object Special1 : ActionWithAllTypesOfInputsBindingV1.Zen(3) - public object Special2 : ActionWithAllTypesOfInputs.Zen(-1) + public object Special2 : ActionWithAllTypesOfInputsBindingV1.Zen(-1) } public sealed class BahEnum( public val stringValue: String, ) { - public object HelloWorld : ActionWithAllTypesOfInputs.BahEnum("helloworld") + public object HelloWorld : ActionWithAllTypesOfInputsBindingV1.BahEnum("helloworld") public class Custom( customStringValue: String, - ) : ActionWithAllTypesOfInputs.BahEnum(customStringValue) + ) : ActionWithAllTypesOfInputsBindingV1.BahEnum(customStringValue) } public sealed class MyEnum( public val stringValue: String, ) { - public object One : ActionWithAllTypesOfInputs.MyEnum("one") + public object One : ActionWithAllTypesOfInputsBindingV1.MyEnum("one") - public object Two : ActionWithAllTypesOfInputs.MyEnum("two") + public object Two : ActionWithAllTypesOfInputsBindingV1.MyEnum("two") - public object Three : ActionWithAllTypesOfInputs.MyEnum("three") + public object Three : ActionWithAllTypesOfInputsBindingV1.MyEnum("three") public class Custom( customStringValue: String, - ) : ActionWithAllTypesOfInputs.MyEnum(customStringValue) + ) : ActionWithAllTypesOfInputsBindingV1.MyEnum(customStringValue) } public sealed class MyInt( @@ -366,9 +366,9 @@ public data class ActionWithAllTypesOfInputs private constructor( ) { public class Value( requestedValue: Int, - ) : ActionWithAllTypesOfInputs.MyInt(requestedValue) + ) : ActionWithAllTypesOfInputsBindingV1.MyInt(requestedValue) - public object TheAnswer : ActionWithAllTypesOfInputs.MyInt(42) + public object TheAnswer : ActionWithAllTypesOfInputsBindingV1.MyInt(42) } public class Outputs( diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1_Untyped.kt similarity index 95% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs_Untyped.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1_Untyped.kt index ebc776fbea..a9b5b41a3a 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputs_Untyped.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV1_Untyped.kt @@ -45,7 +45,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs) + * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs-binding-v1) * * @param fooBar_Untyped Short description * @param bazGoo_Untyped First boolean input! @@ -66,10 +66,10 @@ import kotlin.collections.toTypedArray */ @Deprecated( "Use the typed class instead", - ReplaceWith("ActionWithAllTypesOfInputs"), + ReplaceWith("ActionWithAllTypesOfInputsBindingV1"), ) @ExposedCopyVisibility -public data class ActionWithAllTypesOfInputs_Untyped private constructor( +public data class ActionWithAllTypesOfInputsBindingV1_Untyped private constructor( /** * Short description */ @@ -127,8 +127,8 @@ public data class ActionWithAllTypesOfInputs_Untyped private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", - "action-with-all-types-of-inputs", _customVersion ?: "v3") { +) : RegularAction("john-smith", + "action-with-all-types-of-inputs-binding-v1", _customVersion ?: "v3") { public constructor( vararg pleaseUseNamedArguments: Unit, fooBar_Untyped: String, diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2.kt new file mode 100644 index 0000000000..ba332b8d75 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2.kt @@ -0,0 +1,554 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Float +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs-binding-v2) + * + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param bazGoo <required> First boolean input! + * @param bazGoo_Untyped <required> First boolean input! + * @param binKin Boolean and nullable + * @param binKin_Untyped Boolean and nullable + * @param intPint <required> Integer + * @param intPint_Untyped <required> Integer + * @param floPint <required> Float + * @param floPint_Untyped <required> Float + * @param finBin <required> Enumeration + * @param finBin_Untyped <required> Enumeration + * @param gooZen <required> Integer with special value + * @param gooZen_Untyped <required> Integer with special value + * @param bahEnum <required> Enum with custom naming + * @param bahEnum_Untyped <required> Enum with custom naming + * @param listStrings List of strings + * @param listStrings_Untyped List of strings + * @param listInts List of integers + * @param listInts_Untyped List of integers + * @param listEnums List of enums + * @param listEnums_Untyped List of enums + * @param listIntSpecial List of integer with special values + * @param listIntSpecial_Untyped List of integer with special values + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithAllTypesOfInputsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> Short description + */ + public val fooBar: String? = null, + /** + * <required> Short description + */ + public val fooBar_Untyped: String? = null, + /** + * <required> First boolean input! + */ + public val bazGoo: Boolean? = null, + /** + * <required> First boolean input! + */ + public val bazGoo_Untyped: String? = null, + /** + * Boolean and nullable + */ + public val binKin: Boolean? = null, + /** + * Boolean and nullable + */ + public val binKin_Untyped: String? = null, + /** + * <required> Integer + */ + public val intPint: Int? = null, + /** + * <required> Integer + */ + public val intPint_Untyped: String? = null, + /** + * <required> Float + */ + public val floPint: Float? = null, + /** + * <required> Float + */ + public val floPint_Untyped: String? = null, + /** + * <required> Enumeration + */ + public val finBin: ActionWithAllTypesOfInputsBindingV2.Bin? = null, + /** + * <required> Enumeration + */ + public val finBin_Untyped: String? = null, + /** + * <required> Integer with special value + */ + public val gooZen: ActionWithAllTypesOfInputsBindingV2.Zen? = null, + /** + * <required> Integer with special value + */ + public val gooZen_Untyped: String? = null, + /** + * <required> Enum with custom naming + */ + public val bahEnum: ActionWithAllTypesOfInputsBindingV2.BahEnum? = null, + /** + * <required> Enum with custom naming + */ + public val bahEnum_Untyped: String? = null, + /** + * List of strings + */ + public val listStrings: List? = null, + /** + * List of strings + */ + public val listStrings_Untyped: String? = null, + /** + * List of integers + */ + public val listInts: List? = null, + /** + * List of integers + */ + public val listInts_Untyped: String? = null, + /** + * List of enums + */ + public val listEnums: List? = null, + /** + * List of enums + */ + public val listEnums_Untyped: String? = null, + /** + * List of integer with special values + */ + public val listIntSpecial: List? = null, + /** + * List of integer with special values + */ + public val listIntSpecial_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", + "action-with-all-types-of-inputs-binding-v2", _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-all-types-of-inputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-all-types-of-inputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooBar != null) && (fooBar_Untyped != null))) { + "Only fooBar or fooBar_Untyped must be set, but not both" + } + require((fooBar != null) || (fooBar_Untyped != null)) { + "Either fooBar or fooBar_Untyped must be set, one of them is required" + } + + require(!((bazGoo != null) && (bazGoo_Untyped != null))) { + "Only bazGoo or bazGoo_Untyped must be set, but not both" + } + require((bazGoo != null) || (bazGoo_Untyped != null)) { + "Either bazGoo or bazGoo_Untyped must be set, one of them is required" + } + + require(!((binKin != null) && (binKin_Untyped != null))) { + "Only binKin or binKin_Untyped must be set, but not both" + } + + require(!((intPint != null) && (intPint_Untyped != null))) { + "Only intPint or intPint_Untyped must be set, but not both" + } + require((intPint != null) || (intPint_Untyped != null)) { + "Either intPint or intPint_Untyped must be set, one of them is required" + } + + require(!((floPint != null) && (floPint_Untyped != null))) { + "Only floPint or floPint_Untyped must be set, but not both" + } + require((floPint != null) || (floPint_Untyped != null)) { + "Either floPint or floPint_Untyped must be set, one of them is required" + } + + require(!((finBin != null) && (finBin_Untyped != null))) { + "Only finBin or finBin_Untyped must be set, but not both" + } + require((finBin != null) || (finBin_Untyped != null)) { + "Either finBin or finBin_Untyped must be set, one of them is required" + } + + require(!((gooZen != null) && (gooZen_Untyped != null))) { + "Only gooZen or gooZen_Untyped must be set, but not both" + } + require((gooZen != null) || (gooZen_Untyped != null)) { + "Either gooZen or gooZen_Untyped must be set, one of them is required" + } + + require(!((bahEnum != null) && (bahEnum_Untyped != null))) { + "Only bahEnum or bahEnum_Untyped must be set, but not both" + } + require((bahEnum != null) || (bahEnum_Untyped != null)) { + "Either bahEnum or bahEnum_Untyped must be set, one of them is required" + } + + require(!((listStrings != null) && (listStrings_Untyped != null))) { + "Only listStrings or listStrings_Untyped must be set, but not both" + } + + require(!((listInts != null) && (listInts_Untyped != null))) { + "Only listInts or listInts_Untyped must be set, but not both" + } + + require(!((listEnums != null) && (listEnums_Untyped != null))) { + "Only listEnums or listEnums_Untyped must be set, but not both" + } + + require(!((listIntSpecial != null) && (listIntSpecial_Untyped != null))) { + "Only listIntSpecial or listIntSpecial_Untyped must be set, but not both" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooBar?.let { "foo-bar" to it }, + fooBar_Untyped?.let { "foo-bar" to it }, + bazGoo?.let { "baz-goo" to it.toString() }, + bazGoo_Untyped?.let { "baz-goo" to it }, + binKin?.let { "bin-kin" to it.toString() }, + binKin_Untyped?.let { "bin-kin" to it }, + intPint?.let { "int-pint" to it.toString() }, + intPint_Untyped?.let { "int-pint" to it }, + floPint?.let { "flo-pint" to it.toString() }, + floPint_Untyped?.let { "flo-pint" to it }, + finBin?.let { "fin-bin" to it.stringValue }, + finBin_Untyped?.let { "fin-bin" to it }, + gooZen?.let { "goo-zen" to it.integerValue.toString() }, + gooZen_Untyped?.let { "goo-zen" to it }, + bahEnum?.let { "bah-enum" to it.stringValue }, + bahEnum_Untyped?.let { "bah-enum" to it }, + listStrings?.let { "list-strings" to it.joinToString(",") }, + listStrings_Untyped?.let { "list-strings" to it }, + listInts?.let { "list-ints" to it.joinToString(",") { it.toString() } }, + listInts_Untyped?.let { "list-ints" to it }, + listEnums?.let { "list-enums" to it.joinToString(",") { it.stringValue } }, + listEnums_Untyped?.let { "list-enums" to it }, + listIntSpecial?.let { "list-int-special" to it.joinToString(",") { + it.integerValue.toString() } }, + listIntSpecial_Untyped?.let { "list-int-special" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithAllTypesOfInputsBindingV2 + return fooBar == other.fooBar && + fooBar_Untyped == other.fooBar_Untyped && + bazGoo == other.bazGoo && + bazGoo_Untyped == other.bazGoo_Untyped && + binKin == other.binKin && + binKin_Untyped == other.binKin_Untyped && + intPint == other.intPint && + intPint_Untyped == other.intPint_Untyped && + floPint == other.floPint && + floPint_Untyped == other.floPint_Untyped && + finBin == other.finBin && + finBin_Untyped == other.finBin_Untyped && + gooZen == other.gooZen && + gooZen_Untyped == other.gooZen_Untyped && + bahEnum == other.bahEnum && + bahEnum_Untyped == other.bahEnum_Untyped && + listStrings == other.listStrings && + listStrings_Untyped == other.listStrings_Untyped && + listInts == other.listInts && + listInts_Untyped == other.listInts_Untyped && + listEnums == other.listEnums && + listEnums_Untyped == other.listEnums_Untyped && + listIntSpecial == other.listIntSpecial && + listIntSpecial_Untyped == other.listIntSpecial_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar, + fooBar_Untyped, + bazGoo, + bazGoo_Untyped, + binKin, + binKin_Untyped, + intPint, + intPint_Untyped, + floPint, + floPint_Untyped, + finBin, + finBin_Untyped, + gooZen, + gooZen_Untyped, + bahEnum, + bahEnum_Untyped, + listStrings, + listStrings_Untyped, + listInts, + listInts_Untyped, + listEnums, + listEnums_Untyped, + listIntSpecial, + listIntSpecial_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithAllTypesOfInputsBindingV2(") + append("""fooBar=$fooBar""") + append(", ") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""bazGoo=$bazGoo""") + append(", ") + append("""bazGoo_Untyped=$bazGoo_Untyped""") + append(", ") + append("""binKin=$binKin""") + append(", ") + append("""binKin_Untyped=$binKin_Untyped""") + append(", ") + append("""intPint=$intPint""") + append(", ") + append("""intPint_Untyped=$intPint_Untyped""") + append(", ") + append("""floPint=$floPint""") + append(", ") + append("""floPint_Untyped=$floPint_Untyped""") + append(", ") + append("""finBin=$finBin""") + append(", ") + append("""finBin_Untyped=$finBin_Untyped""") + append(", ") + append("""gooZen=$gooZen""") + append(", ") + append("""gooZen_Untyped=$gooZen_Untyped""") + append(", ") + append("""bahEnum=$bahEnum""") + append(", ") + append("""bahEnum_Untyped=$bahEnum_Untyped""") + append(", ") + append("""listStrings=$listStrings""") + append(", ") + append("""listStrings_Untyped=$listStrings_Untyped""") + append(", ") + append("""listInts=$listInts""") + append(", ") + append("""listInts_Untyped=$listInts_Untyped""") + append(", ") + append("""listEnums=$listEnums""") + append(", ") + append("""listEnums_Untyped=$listEnums_Untyped""") + append(", ") + append("""listIntSpecial=$listIntSpecial""") + append(", ") + append("""listIntSpecial_Untyped=$listIntSpecial_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param bazGoo <required> First boolean input! + * @param bazGoo_Untyped <required> First boolean input! + * @param binKin Boolean and nullable + * @param binKin_Untyped Boolean and nullable + * @param intPint <required> Integer + * @param intPint_Untyped <required> Integer + * @param floPint <required> Float + * @param floPint_Untyped <required> Float + * @param finBin <required> Enumeration + * @param finBin_Untyped <required> Enumeration + * @param gooZen <required> Integer with special value + * @param gooZen_Untyped <required> Integer with special value + * @param bahEnum <required> Enum with custom naming + * @param bahEnum_Untyped <required> Enum with custom naming + * @param listStrings List of strings + * @param listStrings_Untyped List of strings + * @param listInts List of integers + * @param listInts_Untyped List of integers + * @param listEnums List of enums + * @param listEnums_Untyped List of enums + * @param listIntSpecial List of integer with special values + * @param listIntSpecial_Untyped List of integer with special values + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar: String? = this.fooBar, + fooBar_Untyped: String? = this.fooBar_Untyped, + bazGoo: Boolean? = this.bazGoo, + bazGoo_Untyped: String? = this.bazGoo_Untyped, + binKin: Boolean? = this.binKin, + binKin_Untyped: String? = this.binKin_Untyped, + intPint: Int? = this.intPint, + intPint_Untyped: String? = this.intPint_Untyped, + floPint: Float? = this.floPint, + floPint_Untyped: String? = this.floPint_Untyped, + finBin: ActionWithAllTypesOfInputsBindingV2.Bin? = this.finBin, + finBin_Untyped: String? = this.finBin_Untyped, + gooZen: ActionWithAllTypesOfInputsBindingV2.Zen? = this.gooZen, + gooZen_Untyped: String? = this.gooZen_Untyped, + bahEnum: ActionWithAllTypesOfInputsBindingV2.BahEnum? = this.bahEnum, + bahEnum_Untyped: String? = this.bahEnum_Untyped, + listStrings: List? = this.listStrings, + listStrings_Untyped: String? = this.listStrings_Untyped, + listInts: List? = this.listInts, + listInts_Untyped: String? = this.listInts_Untyped, + listEnums: List? = this.listEnums, + listEnums_Untyped: String? = this.listEnums_Untyped, + listIntSpecial: List? = this.listIntSpecial, + listIntSpecial_Untyped: String? = this.listIntSpecial_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithAllTypesOfInputsBindingV2 = ActionWithAllTypesOfInputsBindingV2( + fooBar = fooBar, + fooBar_Untyped = fooBar_Untyped, + bazGoo = bazGoo, + bazGoo_Untyped = bazGoo_Untyped, + binKin = binKin, + binKin_Untyped = binKin_Untyped, + intPint = intPint, + intPint_Untyped = intPint_Untyped, + floPint = floPint, + floPint_Untyped = floPint_Untyped, + finBin = finBin, + finBin_Untyped = finBin_Untyped, + gooZen = gooZen, + gooZen_Untyped = gooZen_Untyped, + bahEnum = bahEnum, + bahEnum_Untyped = bahEnum_Untyped, + listStrings = listStrings, + listStrings_Untyped = listStrings_Untyped, + listInts = listInts, + listInts_Untyped = listInts_Untyped, + listEnums = listEnums, + listEnums_Untyped = listEnums_Untyped, + listIntSpecial = listIntSpecial, + listIntSpecial_Untyped = listIntSpecial_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Outputs = Outputs(stepId) + + public sealed class Bin( + public val stringValue: String, + ) { + public object Foo : ActionWithAllTypesOfInputsBindingV2.Bin("foo") + + public object BooBar : ActionWithAllTypesOfInputsBindingV2.Bin("boo-bar") + + public object Baz123 : ActionWithAllTypesOfInputsBindingV2.Bin("baz123") + + public class Custom( + customStringValue: String, + ) : ActionWithAllTypesOfInputsBindingV2.Bin(customStringValue) + } + + public sealed class Zen( + public val integerValue: Int, + ) { + public class Value( + requestedValue: Int, + ) : ActionWithAllTypesOfInputsBindingV2.Zen(requestedValue) + + public object Special1 : ActionWithAllTypesOfInputsBindingV2.Zen(3) + + public object Special2 : ActionWithAllTypesOfInputsBindingV2.Zen(-1) + } + + public sealed class BahEnum( + public val stringValue: String, + ) { + public object HelloWorld : ActionWithAllTypesOfInputsBindingV2.BahEnum("helloworld") + + public class Custom( + customStringValue: String, + ) : ActionWithAllTypesOfInputsBindingV2.BahEnum(customStringValue) + } + + public sealed class MyEnum( + public val stringValue: String, + ) { + public object One : ActionWithAllTypesOfInputsBindingV2.MyEnum("one") + + public object Two : ActionWithAllTypesOfInputsBindingV2.MyEnum("two") + + public object Three : ActionWithAllTypesOfInputsBindingV2.MyEnum("three") + + public class Custom( + customStringValue: String, + ) : ActionWithAllTypesOfInputsBindingV2.MyEnum(customStringValue) + } + + public sealed class MyInt( + public val integerValue: Int, + ) { + public class Value( + requestedValue: Int, + ) : ActionWithAllTypesOfInputsBindingV2.MyInt(requestedValue) + + public object TheAnswer : ActionWithAllTypesOfInputsBindingV2.MyInt(42) + } + + public class Outputs( + stepId: String, + ) : Action.Outputs(stepId) { + /** + * Cool output! + */ + public val bazGoo: String = "steps.$stepId.outputs.baz-goo" + } +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2_Untyped.kt new file mode 100644 index 0000000000..bc63eeb7f2 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsBindingV2_Untyped.kt @@ -0,0 +1,295 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress( + "UNUSED_PARAMETER", + "DEPRECATION", +) + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Deprecated +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * ```text + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!! WARNING !!! + * !!! !!! + * !!! This action binding has no typings provided. All inputs will !!! + * !!! have a default type of String. !!! + * !!! To be able to use this action in a type-safe way, ask the !!! + * !!! action's owner to provide the typings using !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing !!! + * !!! !!! + * !!! or if it's impossible, contribute typings to a community-driven !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing-catalog !!! + * !!! !!! + * !!! This '_Untyped' binding will be available even once the typings !!! + * !!! are added. !!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ``` + * + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-all-types-of-inputs-binding-v2) + * + * @param fooBar_Untyped Short description + * @param bazGoo_Untyped First boolean input! + * @param binKin_Untyped Boolean and nullable + * @param intPint_Untyped Integer + * @param floPint_Untyped Float + * @param finBin_Untyped Enumeration + * @param gooZen_Untyped Integer with special value + * @param bahEnum_Untyped Enum with custom naming + * @param listStrings_Untyped List of strings + * @param listInts_Untyped List of integers + * @param listEnums_Untyped List of enums + * @param listIntSpecial_Untyped List of integer with special values + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +@Deprecated( + "Use the typed class instead", + ReplaceWith("ActionWithAllTypesOfInputsBindingV2"), +) +public class ActionWithAllTypesOfInputsBindingV2_Untyped( + vararg pleaseUseNamedArguments: Unit, + /** + * Short description + */ + public val fooBar_Untyped: String, + /** + * First boolean input! + */ + public val bazGoo_Untyped: String, + /** + * Boolean and nullable + */ + public val binKin_Untyped: String? = null, + /** + * Integer + */ + public val intPint_Untyped: String, + /** + * Float + */ + public val floPint_Untyped: String, + /** + * Enumeration + */ + public val finBin_Untyped: String, + /** + * Integer with special value + */ + public val gooZen_Untyped: String, + /** + * Enum with custom naming + */ + public val bahEnum_Untyped: String, + /** + * List of strings + */ + public val listStrings_Untyped: String? = null, + /** + * List of integers + */ + public val listInts_Untyped: String? = null, + /** + * List of enums + */ + public val listEnums_Untyped: String? = null, + /** + * List of integer with special values + */ + public val listIntSpecial_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", + "action-with-all-types-of-inputs-binding-v2", _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-all-types-of-inputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-all-types-of-inputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + "foo-bar" to fooBar_Untyped, + "baz-goo" to bazGoo_Untyped, + binKin_Untyped?.let { "bin-kin" to it }, + "int-pint" to intPint_Untyped, + "flo-pint" to floPint_Untyped, + "fin-bin" to finBin_Untyped, + "goo-zen" to gooZen_Untyped, + "bah-enum" to bahEnum_Untyped, + listStrings_Untyped?.let { "list-strings" to it }, + listInts_Untyped?.let { "list-ints" to it }, + listEnums_Untyped?.let { "list-enums" to it }, + listIntSpecial_Untyped?.let { "list-int-special" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithAllTypesOfInputsBindingV2_Untyped + return fooBar_Untyped == other.fooBar_Untyped && + bazGoo_Untyped == other.bazGoo_Untyped && + binKin_Untyped == other.binKin_Untyped && + intPint_Untyped == other.intPint_Untyped && + floPint_Untyped == other.floPint_Untyped && + finBin_Untyped == other.finBin_Untyped && + gooZen_Untyped == other.gooZen_Untyped && + bahEnum_Untyped == other.bahEnum_Untyped && + listStrings_Untyped == other.listStrings_Untyped && + listInts_Untyped == other.listInts_Untyped && + listEnums_Untyped == other.listEnums_Untyped && + listIntSpecial_Untyped == other.listIntSpecial_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar_Untyped, + bazGoo_Untyped, + binKin_Untyped, + intPint_Untyped, + floPint_Untyped, + finBin_Untyped, + gooZen_Untyped, + bahEnum_Untyped, + listStrings_Untyped, + listInts_Untyped, + listEnums_Untyped, + listIntSpecial_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithAllTypesOfInputsBindingV2_Untyped(") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""bazGoo_Untyped=$bazGoo_Untyped""") + append(", ") + append("""binKin_Untyped=$binKin_Untyped""") + append(", ") + append("""intPint_Untyped=$intPint_Untyped""") + append(", ") + append("""floPint_Untyped=$floPint_Untyped""") + append(", ") + append("""finBin_Untyped=$finBin_Untyped""") + append(", ") + append("""gooZen_Untyped=$gooZen_Untyped""") + append(", ") + append("""bahEnum_Untyped=$bahEnum_Untyped""") + append(", ") + append("""listStrings_Untyped=$listStrings_Untyped""") + append(", ") + append("""listInts_Untyped=$listInts_Untyped""") + append(", ") + append("""listEnums_Untyped=$listEnums_Untyped""") + append(", ") + append("""listIntSpecial_Untyped=$listIntSpecial_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar_Untyped Short description + * @param bazGoo_Untyped First boolean input! + * @param binKin_Untyped Boolean and nullable + * @param intPint_Untyped Integer + * @param floPint_Untyped Float + * @param finBin_Untyped Enumeration + * @param gooZen_Untyped Integer with special value + * @param bahEnum_Untyped Enum with custom naming + * @param listStrings_Untyped List of strings + * @param listInts_Untyped List of integers + * @param listEnums_Untyped List of enums + * @param listIntSpecial_Untyped List of integer with special values + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar_Untyped: String = this.fooBar_Untyped, + bazGoo_Untyped: String = this.bazGoo_Untyped, + binKin_Untyped: String? = this.binKin_Untyped, + intPint_Untyped: String = this.intPint_Untyped, + floPint_Untyped: String = this.floPint_Untyped, + finBin_Untyped: String = this.finBin_Untyped, + gooZen_Untyped: String = this.gooZen_Untyped, + bahEnum_Untyped: String = this.bahEnum_Untyped, + listStrings_Untyped: String? = this.listStrings_Untyped, + listInts_Untyped: String? = this.listInts_Untyped, + listEnums_Untyped: String? = this.listEnums_Untyped, + listIntSpecial_Untyped: String? = this.listIntSpecial_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithAllTypesOfInputsBindingV2_Untyped = ActionWithAllTypesOfInputsBindingV2_Untyped( + fooBar_Untyped = fooBar_Untyped, + bazGoo_Untyped = bazGoo_Untyped, + binKin_Untyped = binKin_Untyped, + intPint_Untyped = intPint_Untyped, + floPint_Untyped = floPint_Untyped, + finBin_Untyped = finBin_Untyped, + gooZen_Untyped = gooZen_Untyped, + bahEnum_Untyped = bahEnum_Untyped, + listStrings_Untyped = listStrings_Untyped, + listInts_Untyped = listInts_Untyped, + listEnums_Untyped = listEnums_Untyped, + listIntSpecial_Untyped = listIntSpecial_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Outputs = Outputs(stepId) + + public class Outputs( + stepId: String, + ) : Action.Outputs(stepId) { + /** + * Cool output! + */ + public val bazGoo: String = "steps.$stepId.outputs.baz-goo" + } +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsTest.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsTest.kt index 65098f0291..bd02aaf418 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsTest.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithAllTypesOfInputsTest.kt @@ -1,169 +1,292 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.bindingsfromunittests -import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithAllTypesOfInputs +import io.github.typesafegithub.workflows.actionbindinggenerator.constructAction +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V1 +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V2 +import io.github.typesafegithub.workflows.actionbindinggenerator.withAllBindingVersions +import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithAllTypesOfInputsBindingV1 +import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithAllTypesOfInputsBindingV2 import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe class ActionWithAllTypesOfInputsTest : DescribeSpec({ - it("correctly translates all types of inputs") { - // given - val action = ActionWithAllTypesOfInputs( - fooBar = "test", - bazGoo = true, - binKin = false, - intPint = 43, - floPint = 123.456f, - finBin = ActionWithAllTypesOfInputs.Bin.BooBar, - gooZen = ActionWithAllTypesOfInputs.Zen.Special1, - bahEnum = ActionWithAllTypesOfInputs.BahEnum.HelloWorld, - listStrings = listOf("hello", "world"), - listInts = listOf(1, 42), - listEnums = listOf(ActionWithAllTypesOfInputs.MyEnum.One, ActionWithAllTypesOfInputs.MyEnum.Three), - listIntSpecial = listOf(ActionWithAllTypesOfInputs.MyInt.TheAnswer, ActionWithAllTypesOfInputs.MyInt.Value(0)) - ) + context("correctly translates all types of inputs") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "bazGoo" to true, + "binKin" to false, + "intPint" to 43, + "floPint" to 123.456f, + "finBin" to bindingVersion.finBin, + "gooZen" to bindingVersion.gooZen, + "bahEnum" to bindingVersion.bahEnum, + "listStrings" to listOf("hello", "world"), + "listInts" to listOf(1, 42), + "listEnums" to bindingVersion.listEnums, + "listIntSpecial" to bindingVersion.listIntSpecial, + ), + ) - // when - val yaml = action.toYamlArguments() - - // then - yaml shouldBe linkedMapOf( - "foo-bar" to "test", - "baz-goo" to "true", - "bin-kin" to "false", - "int-pint" to "43", - "flo-pint" to "123.456", - "fin-bin" to "boo-bar", - "goo-zen" to "3", - "bah-enum" to "helloworld", - "list-strings" to "hello,world", - "list-ints" to "1,42", - "list-enums" to "one,three", - "list-int-special" to "42,0" - ) + // when + val yaml = action.toYamlArguments() + + // then + yaml shouldBe linkedMapOf( + "foo-bar" to "test", + "baz-goo" to "true", + "bin-kin" to "false", + "int-pint" to "43", + "flo-pint" to "123.456", + "fin-bin" to "boo-bar", + "goo-zen" to "3", + "bah-enum" to "helloworld", + "list-strings" to "hello,world", + "list-ints" to "1,42", + "list-enums" to "one,three", + "list-int-special" to "42,0" + ) + } } - it("works for custom values") { - // given - val action = ActionWithAllTypesOfInputs( - fooBar = "test", - bazGoo = true, - binKin = false, - intPint = 43, - floPint = 123.456f, - finBin = ActionWithAllTypesOfInputs.Bin.Custom("this-is-custom!"), - gooZen = ActionWithAllTypesOfInputs.Zen.Value(123), - bahEnum = ActionWithAllTypesOfInputs.BahEnum.Custom("very-custom"), - ) + context("works for custom values") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "bazGoo" to true, + "binKin" to false, + "intPint" to 43, + "floPint" to 123.456f, + "finBin" to bindingVersion.customFinBin, + "gooZen" to bindingVersion.customGooZen, + "bahEnum" to bindingVersion.customBahEnum, + ), + ) - // when - val yaml = action.toYamlArguments() - - // then - yaml shouldBe linkedMapOf( - "foo-bar" to "test", - "baz-goo" to "true", - "bin-kin" to "false", - "int-pint" to "43", - "flo-pint" to "123.456", - "fin-bin" to "this-is-custom!", - "goo-zen" to "123", - "bah-enum" to "very-custom", - ) + // when + val yaml = action.toYamlArguments() + + // then + yaml shouldBe linkedMapOf( + "foo-bar" to "test", + "baz-goo" to "true", + "bin-kin" to "false", + "int-pint" to "43", + "flo-pint" to "123.456", + "fin-bin" to "this-is-custom!", + "goo-zen" to "123", + "bah-enum" to "very-custom", + ) + } } - it("untyped input is sufficient for required input") { - // given - val action = ActionWithAllTypesOfInputs( - fooBar = "test", - bazGoo_Untyped = "\${{ 1 == 1 }}", - binKin = false, - intPint = 43, - floPint = 123.456f, - finBin = ActionWithAllTypesOfInputs.Bin.Custom("this-is-custom!"), - gooZen = ActionWithAllTypesOfInputs.Zen.Value(123), - bahEnum = ActionWithAllTypesOfInputs.BahEnum.Custom("very-custom"), - ) + context("untyped input is sufficient for required input") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "bazGoo_Untyped" to "\${{ 1 == 1 }}", + "binKin" to false, + "intPint" to 43, + "floPint" to 123.456f, + "finBin" to bindingVersion.customFinBin, + "gooZen" to bindingVersion.customGooZen, + "bahEnum" to bindingVersion.customBahEnum, + ), + ) - // when - val yaml = action.toYamlArguments() - - // then - yaml shouldBe linkedMapOf( - "foo-bar" to "test", - "baz-goo" to "\${{ 1 == 1 }}", - "bin-kin" to "false", - "int-pint" to "43", - "flo-pint" to "123.456", - "fin-bin" to "this-is-custom!", - "goo-zen" to "123", - "bah-enum" to "very-custom", - ) + // when + val yaml = action.toYamlArguments() + + // then + yaml shouldBe linkedMapOf( + "foo-bar" to "test", + "baz-goo" to "\${{ 1 == 1 }}", + "bin-kin" to "false", + "int-pint" to "43", + "flo-pint" to "123.456", + "fin-bin" to "this-is-custom!", + "goo-zen" to "123", + "bah-enum" to "very-custom", + ) + } } - it("validates required inputs are not missing") { - // expect - val exception = - shouldThrow { - ActionWithAllTypesOfInputs() - } - exception.message shouldBe "Either fooBar or fooBar_Untyped must be set, one of them is required" + context("validates required inputs are not missing") { + withAllBindingVersions { bindingVersion -> + // expect + val exception = + shouldThrow { + constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + ) + } + exception.message shouldBe "Either fooBar or fooBar_Untyped must be set, one of them is required" + } } - it("validates required inputs are not supplied typed and untyped") { - // expect - val exception = - shouldThrow { - ActionWithAllTypesOfInputs( - fooBar = "test", - fooBar_Untyped = "untyped test", - ) - } - exception.message shouldBe "Only fooBar or fooBar_Untyped must be set, but not both" + context("validates required inputs are not supplied typed and untyped") { + withAllBindingVersions { bindingVersion -> + // expect + val exception = + shouldThrow { + constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "fooBar_Untyped" to "untyped test", + ), + ) + } + exception.message shouldBe "Only fooBar or fooBar_Untyped must be set, but not both" + } } - it("validates not-required inputs are not supplied typed and untyped") { - // expect - val exception = - shouldThrow { - ActionWithAllTypesOfInputs( - fooBar = "test", - bazGoo_Untyped = "\${{ 1 == 1 }}", - binKin = false, - intPint = 43, - floPint = 123.456f, - finBin = ActionWithAllTypesOfInputs.Bin.Custom("this-is-custom!"), - gooZen = ActionWithAllTypesOfInputs.Zen.Value(123), - bahEnum = ActionWithAllTypesOfInputs.BahEnum.Custom("very-custom"), - listStrings = listOf("test"), - listStrings_Untyped = "untyped test", - ) - } - exception.message shouldBe "Only listStrings or listStrings_Untyped must be set, but not both" + context("validates not-required inputs are not supplied typed and untyped") { + withAllBindingVersions { bindingVersion -> + // expect + val exception = + shouldThrow { + constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "bazGoo_Untyped" to "\${{ 1 == 1 }}", + "binKin" to false, + "intPint" to 43, + "floPint" to 123.456f, + "finBin" to bindingVersion.customFinBin, + "gooZen" to bindingVersion.customGooZen, + "bahEnum" to bindingVersion.customBahEnum, + "listStrings" to listOf("test"), + "listStrings_Untyped" to "untyped test", + ), + ) + } + exception.message shouldBe "Only listStrings or listStrings_Untyped must be set, but not both" + } } - it("exposes copy method") { - // given - val action = ActionWithAllTypesOfInputs( - fooBar = "test", - bazGoo = true, - binKin = false, - intPint = 43, - floPint = 123.456f, - finBin = ActionWithAllTypesOfInputs.Bin.BooBar, - gooZen = ActionWithAllTypesOfInputs.Zen.Special1, - bahEnum = ActionWithAllTypesOfInputs.BahEnum.HelloWorld, - listStrings = listOf("hello", "world"), - listInts = listOf(1, 42), - listEnums = listOf(ActionWithAllTypesOfInputs.MyEnum.One, ActionWithAllTypesOfInputs.MyEnum.Three), - listIntSpecial = listOf(ActionWithAllTypesOfInputs.MyInt.TheAnswer, ActionWithAllTypesOfInputs.MyInt.Value(0)) - ) + context("exposes copy method") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithAllTypesOfInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "test", + "bazGoo" to true, + "binKin" to false, + "intPint" to 43, + "floPint" to 123.456f, + "finBin" to bindingVersion.finBin, + "gooZen" to bindingVersion.gooZen, + "bahEnum" to bindingVersion.bahEnum, + "listStrings" to listOf("hello", "world"), + "listInts" to listOf(1, 42), + "listEnums" to bindingVersion.listEnums, + "listIntSpecial" to bindingVersion.listIntSpecial, + ), + ) + + when (bindingVersion) { + V1 -> { + // when + action as ActionWithAllTypesOfInputsBindingV1 + @Suppress("DATA_CLASS_INVISIBLE_COPY_USAGE_WARNING") + val actionWithOneChange = action.copy(fooBar = "another") - // when - @Suppress("DATA_CLASS_INVISIBLE_COPY_USAGE_WARNING") - val actionWithOneChange = action.copy(fooBar = "another") + // then + actionWithOneChange.fooBar shouldBe "another" + } - // then - actionWithOneChange.fooBar shouldBe "another" + V2 -> { + // when + action as ActionWithAllTypesOfInputsBindingV2 + val actionWithOneChange = action.copy(fooBar = "another") + + // then + actionWithOneChange.fooBar shouldBe "another" + } + } + } } }) + +private val BindingVersion.finBin + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.Bin.BooBar + V2 -> ActionWithAllTypesOfInputsBindingV2.Bin.BooBar + } + +private val BindingVersion.customFinBin + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.Bin.Custom("this-is-custom!") + V2 -> ActionWithAllTypesOfInputsBindingV2.Bin.Custom("this-is-custom!") + } + +private val BindingVersion.gooZen + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.Zen.Special1 + V2 -> ActionWithAllTypesOfInputsBindingV2.Zen.Special1 + } + +private val BindingVersion.customGooZen + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.Zen.Value(123) + V2 -> ActionWithAllTypesOfInputsBindingV2.Zen.Value(123) + } + +private val BindingVersion.bahEnum + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.BahEnum.HelloWorld + V2 -> ActionWithAllTypesOfInputsBindingV2.BahEnum.HelloWorld + } + +private val BindingVersion.customBahEnum + get() = when (this) { + V1 -> ActionWithAllTypesOfInputsBindingV1.BahEnum.Custom("very-custom") + V2 -> ActionWithAllTypesOfInputsBindingV2.BahEnum.Custom("very-custom") + } + +private val BindingVersion.listEnums + get() = when (this) { + V1 -> listOf(ActionWithAllTypesOfInputsBindingV1.MyEnum.One, ActionWithAllTypesOfInputsBindingV1.MyEnum.Three) + V2 -> listOf(ActionWithAllTypesOfInputsBindingV2.MyEnum.One, ActionWithAllTypesOfInputsBindingV2.MyEnum.Three) + } + +private val BindingVersion.listIntSpecial + get() = when (this) { + V1 -> listOf( + ActionWithAllTypesOfInputsBindingV1.MyInt.TheAnswer, + ActionWithAllTypesOfInputsBindingV1.MyInt.Value(0), + ) + + V2 -> listOf( + ActionWithAllTypesOfInputsBindingV2.MyInt.TheAnswer, + ActionWithAllTypesOfInputsBindingV2.MyInt.Value(0), + ) + } diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClash.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV1.kt similarity index 89% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClash.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV1.kt index 7369881348..466cc99505 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClash.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV1.kt @@ -24,7 +24,8 @@ import kotlin.collections.toTypedArray * * Description * - * [Action on GitHub](https://github.com/john-smith/action-with-deprecated-input-and-name-clash) + * [Action on + * GitHub](https://github.com/john-smith/action-with-deprecated-input-and-name-clash-binding-v1) * * @param fooBar <required> Foo bar - new * @param fooBar_Untyped <required> Foo bar - new @@ -34,7 +35,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithDeprecatedInputAndNameClash private constructor( +public data class ActionWithDeprecatedInputAndNameClashBindingV1 private constructor( /** * <required> Foo bar - new */ @@ -52,8 +53,8 @@ public data class ActionWithDeprecatedInputAndNameClash private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-deprecated-input-and-name-clash", - _customVersion ?: "v2") { +) : RegularAction("john-smith", + "action-with-deprecated-input-and-name-clash-binding-v1", _customVersion ?: "v2") { init { require(!((fooBar != null) && (fooBar_Untyped != null))) { "Only fooBar or fooBar_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV2.kt new file mode 100644 index 0000000000..0bd420ee20 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithDeprecatedInputAndNameClashBindingV2.kt @@ -0,0 +1,136 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Some Action + * + * Description + * + * [Action on + * GitHub](https://github.com/john-smith/action-with-deprecated-input-and-name-clash-binding-v2) + * + * @param fooBar <required> Foo bar - new + * @param fooBar_Untyped <required> Foo bar - new + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithDeprecatedInputAndNameClashBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> Foo bar - new + */ + public val fooBar: String? = null, + /** + * <required> Foo bar - new + */ + public val fooBar_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", + "action-with-deprecated-input-and-name-clash-binding-v2", _customVersion ?: "v2") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-deprecated-input-and-name-clash-binding-v2@v2 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-deprecated-input-and-name-clash-binding-v2@v2 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooBar != null) && (fooBar_Untyped != null))) { + "Only fooBar or fooBar_Untyped must be set, but not both" + } + require((fooBar != null) || (fooBar_Untyped != null)) { + "Either fooBar or fooBar_Untyped must be set, one of them is required" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooBar?.let { "fooBar" to it }, + fooBar_Untyped?.let { "fooBar" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithDeprecatedInputAndNameClashBindingV2 + return fooBar == other.fooBar && + fooBar_Untyped == other.fooBar_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar, + fooBar_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithDeprecatedInputAndNameClashBindingV2(") + append("""fooBar=$fooBar""") + append(", ") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar <required> Foo bar - new + * @param fooBar_Untyped <required> Foo bar - new + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar: String? = this.fooBar, + fooBar_Untyped: String? = this.fooBar_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithDeprecatedInputAndNameClashBindingV2 = + ActionWithDeprecatedInputAndNameClashBindingV2( + fooBar = fooBar, + fooBar_Untyped = fooBar_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV1.kt similarity index 95% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV1.kt index b9d03a046b..28d92166f0 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV1.kt @@ -24,7 +24,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-fancy-chars-in-docs) + * [Action on GitHub](https://github.com/john-smith/action-with-fancy-chars-in-docs-binding-v1) * * @param nestedKotlinComments This is a /* test */ * @param nestedKotlinComments_Untyped This is a /* test */ @@ -36,7 +36,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithFancyCharsInDocs private constructor( +public data class ActionWithFancyCharsInDocsBindingV1 private constructor( /** * This is a /* test */ */ @@ -62,8 +62,8 @@ public data class ActionWithFancyCharsInDocs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-fancy-chars-in-docs", _customVersion ?: - "v3") { +) : RegularAction("john-smith", "action-with-fancy-chars-in-docs-binding-v1", + _customVersion ?: "v3") { init { require(!((nestedKotlinComments != null) && (nestedKotlinComments_Untyped != null))) { "Only nestedKotlinComments or nestedKotlinComments_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV2.kt new file mode 100644 index 0000000000..5d8bc52618 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithFancyCharsInDocsBindingV2.kt @@ -0,0 +1,161 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-fancy-chars-in-docs-binding-v2) + * + * @param nestedKotlinComments This is a /* test */ + * @param nestedKotlinComments_Untyped This is a /* test */ + * @param percent For example "100%" + * @param percent_Untyped For example "100%" + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithFancyCharsInDocsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * This is a /* test */ + */ + public val nestedKotlinComments: String? = null, + /** + * This is a /* test */ + */ + public val nestedKotlinComments_Untyped: String? = null, + /** + * For example "100%" + */ + public val percent: String? = null, + /** + * For example "100%" + */ + public val percent_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-fancy-chars-in-docs-binding-v2", + _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-fancy-chars-in-docs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-fancy-chars-in-docs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((nestedKotlinComments != null) && (nestedKotlinComments_Untyped != null))) { + "Only nestedKotlinComments or nestedKotlinComments_Untyped must be set, but not both" + } + + require(!((percent != null) && (percent_Untyped != null))) { + "Only percent or percent_Untyped must be set, but not both" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + nestedKotlinComments?.let { "nested-kotlin-comments" to it }, + nestedKotlinComments_Untyped?.let { "nested-kotlin-comments" to it }, + percent?.let { "percent" to it }, + percent_Untyped?.let { "percent" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithFancyCharsInDocsBindingV2 + return nestedKotlinComments == other.nestedKotlinComments && + nestedKotlinComments_Untyped == other.nestedKotlinComments_Untyped && + percent == other.percent && + percent_Untyped == other.percent_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + nestedKotlinComments, + nestedKotlinComments_Untyped, + percent, + percent_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithFancyCharsInDocsBindingV2(") + append("""nestedKotlinComments=$nestedKotlinComments""") + append(", ") + append("""nestedKotlinComments_Untyped=$nestedKotlinComments_Untyped""") + append(", ") + append("""percent=$percent""") + append(", ") + append("""percent_Untyped=$percent_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param nestedKotlinComments This is a /* test */ + * @param nestedKotlinComments_Untyped This is a /* test */ + * @param percent For example "100%" + * @param percent_Untyped For example "100%" + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + nestedKotlinComments: String? = this.nestedKotlinComments, + nestedKotlinComments_Untyped: String? = this.nestedKotlinComments_Untyped, + percent: String? = this.percent, + percent_Untyped: String? = this.percent_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithFancyCharsInDocsBindingV2 = ActionWithFancyCharsInDocsBindingV2( + nestedKotlinComments = nestedKotlinComments, + nestedKotlinComments_Untyped = nestedKotlinComments_Untyped, + percent = percent, + percent_Untyped = percent_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingType.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV1.kt similarity index 85% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingType.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV1.kt index bd8c9612c1..dad3109c6c 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingType.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV1.kt @@ -25,7 +25,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-inputs-sharing-type) + * [Action on GitHub](https://github.com/john-smith/action-with-inputs-sharing-type-binding-v1) * * @param fooOne <required> * @param fooOne_Untyped <required> @@ -37,11 +37,11 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithInputsSharingType private constructor( +public data class ActionWithInputsSharingTypeBindingV1 private constructor( /** * <required> */ - public val fooOne: ActionWithInputsSharingType.Foo? = null, + public val fooOne: ActionWithInputsSharingTypeBindingV1.Foo? = null, /** * <required> */ @@ -49,12 +49,12 @@ public data class ActionWithInputsSharingType private constructor( /** * <required> */ - public val fooTwo: ActionWithInputsSharingType.Foo? = null, + public val fooTwo: ActionWithInputsSharingTypeBindingV1.Foo? = null, /** * <required> */ public val fooTwo_Untyped: String? = null, - public val fooThree: ActionWithInputsSharingType.Foo? = null, + public val fooThree: ActionWithInputsSharingTypeBindingV1.Foo? = null, public val fooThree_Untyped: String? = null, /** * Type-unsafe map where you can put any inputs that are not yet supported by the binding @@ -65,8 +65,8 @@ public data class ActionWithInputsSharingType private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-inputs-sharing-type", _customVersion ?: - "v3") { +) : RegularAction("john-smith", "action-with-inputs-sharing-type-binding-v1", + _customVersion ?: "v3") { init { require(!((fooOne != null) && (fooOne_Untyped != null))) { "Only fooOne or fooOne_Untyped must be set, but not both" @@ -89,11 +89,11 @@ public data class ActionWithInputsSharingType private constructor( public constructor( vararg pleaseUseNamedArguments: Unit, - fooOne: ActionWithInputsSharingType.Foo? = null, + fooOne: ActionWithInputsSharingTypeBindingV1.Foo? = null, fooOne_Untyped: String? = null, - fooTwo: ActionWithInputsSharingType.Foo? = null, + fooTwo: ActionWithInputsSharingTypeBindingV1.Foo? = null, fooTwo_Untyped: String? = null, - fooThree: ActionWithInputsSharingType.Foo? = null, + fooThree: ActionWithInputsSharingTypeBindingV1.Foo? = null, fooThree_Untyped: String? = null, _customInputs: Map = mapOf(), _customVersion: String? = null, @@ -121,8 +121,8 @@ public data class ActionWithInputsSharingType private constructor( ) { public class Value( requestedValue: Int, - ) : ActionWithInputsSharingType.Foo(requestedValue) + ) : ActionWithInputsSharingTypeBindingV1.Foo(requestedValue) - public object Special1 : ActionWithInputsSharingType.Foo(3) + public object Special1 : ActionWithInputsSharingTypeBindingV1.Foo(3) } } diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV2.kt new file mode 100644 index 0000000000..ac941fe82a --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithInputsSharingTypeBindingV2.kt @@ -0,0 +1,197 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-inputs-sharing-type-binding-v2) + * + * @param fooOne <required> + * @param fooOne_Untyped <required> + * @param fooTwo <required> + * @param fooTwo_Untyped <required> + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithInputsSharingTypeBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> + */ + public val fooOne: ActionWithInputsSharingTypeBindingV2.Foo? = null, + /** + * <required> + */ + public val fooOne_Untyped: String? = null, + /** + * <required> + */ + public val fooTwo: ActionWithInputsSharingTypeBindingV2.Foo? = null, + /** + * <required> + */ + public val fooTwo_Untyped: String? = null, + public val fooThree: ActionWithInputsSharingTypeBindingV2.Foo? = null, + public val fooThree_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-inputs-sharing-type-binding-v2", + _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-inputs-sharing-type-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-inputs-sharing-type-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooOne != null) && (fooOne_Untyped != null))) { + "Only fooOne or fooOne_Untyped must be set, but not both" + } + require((fooOne != null) || (fooOne_Untyped != null)) { + "Either fooOne or fooOne_Untyped must be set, one of them is required" + } + + require(!((fooTwo != null) && (fooTwo_Untyped != null))) { + "Only fooTwo or fooTwo_Untyped must be set, but not both" + } + require((fooTwo != null) || (fooTwo_Untyped != null)) { + "Either fooTwo or fooTwo_Untyped must be set, one of them is required" + } + + require(!((fooThree != null) && (fooThree_Untyped != null))) { + "Only fooThree or fooThree_Untyped must be set, but not both" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooOne?.let { "foo-one" to it.integerValue.toString() }, + fooOne_Untyped?.let { "foo-one" to it }, + fooTwo?.let { "foo-two" to it.integerValue.toString() }, + fooTwo_Untyped?.let { "foo-two" to it }, + fooThree?.let { "foo-three" to it.integerValue.toString() }, + fooThree_Untyped?.let { "foo-three" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithInputsSharingTypeBindingV2 + return fooOne == other.fooOne && + fooOne_Untyped == other.fooOne_Untyped && + fooTwo == other.fooTwo && + fooTwo_Untyped == other.fooTwo_Untyped && + fooThree == other.fooThree && + fooThree_Untyped == other.fooThree_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooOne, + fooOne_Untyped, + fooTwo, + fooTwo_Untyped, + fooThree, + fooThree_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithInputsSharingTypeBindingV2(") + append("""fooOne=$fooOne""") + append(", ") + append("""fooOne_Untyped=$fooOne_Untyped""") + append(", ") + append("""fooTwo=$fooTwo""") + append(", ") + append("""fooTwo_Untyped=$fooTwo_Untyped""") + append(", ") + append("""fooThree=$fooThree""") + append(", ") + append("""fooThree_Untyped=$fooThree_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooOne <required> + * @param fooOne_Untyped <required> + * @param fooTwo <required> + * @param fooTwo_Untyped <required> + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooOne: ActionWithInputsSharingTypeBindingV2.Foo? = this.fooOne, + fooOne_Untyped: String? = this.fooOne_Untyped, + fooTwo: ActionWithInputsSharingTypeBindingV2.Foo? = this.fooTwo, + fooTwo_Untyped: String? = this.fooTwo_Untyped, + fooThree: ActionWithInputsSharingTypeBindingV2.Foo? = this.fooThree, + fooThree_Untyped: String? = this.fooThree_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithInputsSharingTypeBindingV2 = ActionWithInputsSharingTypeBindingV2( + fooOne = fooOne, + fooOne_Untyped = fooOne_Untyped, + fooTwo = fooTwo, + fooTwo_Untyped = fooTwo_Untyped, + fooThree = fooThree, + fooThree_Untyped = fooThree_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) + + public sealed class Foo( + public val integerValue: Int, + ) { + public class Value( + requestedValue: Int, + ) : ActionWithInputsSharingTypeBindingV2.Foo(requestedValue) + + public object Special1 : ActionWithInputsSharingTypeBindingV2.Foo(3) + } +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV1.kt similarity index 93% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV1.kt index 09f420ec13..6fe0b07b52 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV1.kt @@ -22,7 +22,7 @@ import kotlin.collections.Map * * Description * - * [Action on GitHub](https://github.com/john-smith/action-with-no-inputs) + * [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-binding-v1) * * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by * the binding @@ -30,7 +30,7 @@ import kotlin.collections.Map * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithNoInputs private constructor( +public data class ActionWithNoInputsBindingV1 private constructor( /** * Type-unsafe map where you can put any inputs that are not yet supported by the binding */ @@ -40,7 +40,8 @@ public data class ActionWithNoInputs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-no-inputs", _customVersion ?: "v3") { +) : RegularAction("john-smith", "action-with-no-inputs-binding-v1", _customVersion + ?: "v3") { public constructor( vararg pleaseUseNamedArguments: Unit, _customInputs: Map = mapOf(), diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV2.kt new file mode 100644 index 0000000000..0b3bd86607 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoInputsBindingV2.kt @@ -0,0 +1,96 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map + +/** + * Action: Action With No Inputs + * + * Description + * + * [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-binding-v2) + * + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithNoInputsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-no-inputs-binding-v2", _customVersion + ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-no-inputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-no-inputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = LinkedHashMap(_customInputs) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithNoInputsBindingV2 + return _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithNoInputsBindingV2(") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithNoInputsBindingV2 = ActionWithNoInputsBindingV2( + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypings_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV1_Untyped.kt similarity index 96% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypings_Untyped.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV1_Untyped.kt index 4ea05fa363..bdd9d4994e 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypings_Untyped.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV1_Untyped.kt @@ -44,7 +44,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-no-typings) + * [Action on GitHub](https://github.com/john-smith/action-with-no-typings-binding-v1) * * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by * the binding @@ -52,7 +52,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithNoTypings_Untyped private constructor( +public data class ActionWithNoTypingsBindingV1_Untyped private constructor( public val foo_Untyped: String, public val bar_Untyped: String? = null, /** @@ -64,7 +64,8 @@ public data class ActionWithNoTypings_Untyped private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-no-typings", _customVersion ?: "v3") { +) : RegularAction("john-smith", "action-with-no-typings-binding-v1", _customVersion + ?: "v3") { public constructor( vararg pleaseUseNamedArguments: Unit, foo_Untyped: String, diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV2_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV2_Untyped.kt new file mode 100644 index 0000000000..a3e808fbb1 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithNoTypingsBindingV2_Untyped.kt @@ -0,0 +1,138 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * ```text + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!! WARNING !!! + * !!! !!! + * !!! This action binding has no typings provided. All inputs will !!! + * !!! have a default type of String. !!! + * !!! To be able to use this action in a type-safe way, ask the !!! + * !!! action's owner to provide the typings using !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing !!! + * !!! !!! + * !!! or if it's impossible, contribute typings to a community-driven !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing-catalog !!! + * !!! !!! + * !!! This '_Untyped' binding will be available even once the typings !!! + * !!! are added. !!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ``` + * + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-no-typings-binding-v2) + * + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithNoTypingsBindingV2_Untyped( + vararg pleaseUseNamedArguments: Unit, + public val foo_Untyped: String, + public val bar_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-no-typings-binding-v2", _customVersion + ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-no-typings-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-no-typings-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + "foo" to foo_Untyped, + bar_Untyped?.let { "bar" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithNoTypingsBindingV2_Untyped + return foo_Untyped == other.foo_Untyped && + bar_Untyped == other.bar_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + foo_Untyped, + bar_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithNoTypingsBindingV2_Untyped(") + append("""foo_Untyped=$foo_Untyped""") + append(", ") + append("""bar_Untyped=$bar_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + foo_Untyped: String = this.foo_Untyped, + bar_Untyped: String? = this.bar_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithNoTypingsBindingV2_Untyped = ActionWithNoTypingsBindingV2_Untyped( + foo_Untyped = foo_Untyped, + bar_Untyped = bar_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV1.kt similarity index 93% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV1.kt index 1e856b7092..8270000e94 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV1.kt @@ -24,7 +24,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-outputs) + * [Action on GitHub](https://github.com/john-smith/action-with-outputs-binding-v1) * * @param fooBar <required> Short description * @param fooBar_Untyped <required> Short description @@ -34,7 +34,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithOutputs private constructor( +public data class ActionWithOutputsBindingV1 private constructor( /** * <required> Short description */ @@ -52,8 +52,8 @@ public data class ActionWithOutputs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-outputs", _customVersion ?: - "v3") { +) : RegularAction("john-smith", + "action-with-outputs-binding-v1", _customVersion ?: "v3") { init { require(!((fooBar != null) && (fooBar_Untyped != null))) { "Only fooBar or fooBar_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV2.kt new file mode 100644 index 0000000000..98d71b7c54 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsBindingV2.kt @@ -0,0 +1,148 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-outputs-binding-v2) + * + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithOutputsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> Short description + */ + public val fooBar: String? = null, + /** + * <required> Short description + */ + public val fooBar_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", + "action-with-outputs-binding-v2", _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-outputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-outputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooBar != null) && (fooBar_Untyped != null))) { + "Only fooBar or fooBar_Untyped must be set, but not both" + } + require((fooBar != null) || (fooBar_Untyped != null)) { + "Either fooBar or fooBar_Untyped must be set, one of them is required" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooBar?.let { "foo-bar" to it }, + fooBar_Untyped?.let { "foo-bar" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithOutputsBindingV2 + return fooBar == other.fooBar && + fooBar_Untyped == other.fooBar_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar, + fooBar_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithOutputsBindingV2(") + append("""fooBar=$fooBar""") + append(", ") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar: String? = this.fooBar, + fooBar_Untyped: String? = this.fooBar_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithOutputsBindingV2 = ActionWithOutputsBindingV2( + fooBar = fooBar, + fooBar_Untyped = fooBar_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Outputs = Outputs(stepId) + + public class Outputs( + stepId: String, + ) : Action.Outputs(stepId) { + /** + * Cool output! + */ + public val bazGoo: String = "steps.$stepId.outputs.baz-goo" + + /** + * Another output... + */ + public val looWoz: String = "steps.$stepId.outputs.loo-woz" + } +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsTest.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsTest.kt index 780b36f6af..6d5c4c571a 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsTest.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithOutputsTest.kt @@ -1,17 +1,40 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.bindingsfromunittests -import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithOutputs +import io.github.typesafegithub.workflows.actionbindinggenerator.constructAction +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V1 +import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V2 +import io.github.typesafegithub.workflows.actionbindinggenerator.withAllBindingVersions +import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithOutputsBindingV1 +import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithOutputsBindingV2 import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe class ActionWithOutputsTest : DescribeSpec({ - it("fields have correct output placeholders") { - // given - val outputs = ActionWithOutputs(fooBar = "1").buildOutputObject("someStepId") + context("fields have correct output placeholders") { + withAllBindingVersions { bindingVersion -> + // given + val outputs = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithOutputs", + bindingVersion = bindingVersion, + arguments = mapOf("fooBar" to "1"), + ).buildOutputObject("someStepId") - // when & then - outputs.bazGoo shouldBe "steps.someStepId.outputs.baz-goo" - outputs.looWoz shouldBe "steps.someStepId.outputs.loo-woz" - outputs["custom-output"] shouldBe "steps.someStepId.outputs.custom-output" + // when & then + when (bindingVersion) { + V1 -> { + outputs as ActionWithOutputsBindingV1.Outputs + outputs.bazGoo shouldBe "steps.someStepId.outputs.baz-goo" + outputs.looWoz shouldBe "steps.someStepId.outputs.loo-woz" + } + + V2 -> { + outputs as ActionWithOutputsBindingV2.Outputs + outputs.bazGoo shouldBe "steps.someStepId.outputs.baz-goo" + outputs.looWoz shouldBe "steps.someStepId.outputs.loo-woz" + } + } + outputs["custom-output"] shouldBe "steps.someStepId.outputs.custom-output" + } } }) diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1.kt similarity index 95% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1.kt index 05346a83a4..dea8585862 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1.kt @@ -25,7 +25,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings) + * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings-binding-v1) * * @param foo <required> * @param foo_Untyped <required> @@ -35,7 +35,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithPartlyTypings private constructor( +public data class ActionWithPartlyTypingsBindingV1 private constructor( /** * <required> */ @@ -55,8 +55,8 @@ public data class ActionWithPartlyTypings private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-partly-typings", _customVersion ?: - "v3") { +) : RegularAction("john-smith", "action-with-partly-typings-binding-v1", + _customVersion ?: "v3") { init { require(!((foo != null) && (foo_Untyped != null))) { "Only foo or foo_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1_Untyped.kt similarity index 94% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings_Untyped.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1_Untyped.kt index b4f1fdb5ba..5b1d6f123f 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypings_Untyped.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV1_Untyped.kt @@ -45,7 +45,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings) + * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings-binding-v1) * * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by * the binding @@ -54,10 +54,10 @@ import kotlin.collections.toTypedArray */ @Deprecated( "Use the typed class instead", - ReplaceWith("ActionWithPartlyTypings"), + ReplaceWith("ActionWithPartlyTypingsBindingV1"), ) @ExposedCopyVisibility -public data class ActionWithPartlyTypings_Untyped private constructor( +public data class ActionWithPartlyTypingsBindingV1_Untyped private constructor( public val foo_Untyped: String, public val bar_Untyped: String? = null, public val baz_Untyped: String, @@ -70,8 +70,8 @@ public data class ActionWithPartlyTypings_Untyped private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-partly-typings", _customVersion ?: - "v3") { +) : RegularAction("john-smith", "action-with-partly-typings-binding-v1", + _customVersion ?: "v3") { public constructor( vararg pleaseUseNamedArguments: Unit, foo_Untyped: String, diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2.kt new file mode 100644 index 0000000000..ec9390585b --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2.kt @@ -0,0 +1,150 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings-binding-v2) + * + * @param foo <required> + * @param foo_Untyped <required> + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithPartlyTypingsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> + */ + public val foo: Int? = null, + /** + * <required> + */ + public val foo_Untyped: String? = null, + public val bar_Untyped: String? = null, + public val baz_Untyped: String, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-partly-typings-binding-v2", + _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-partly-typings-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-partly-typings-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((foo != null) && (foo_Untyped != null))) { + "Only foo or foo_Untyped must be set, but not both" + } + require((foo != null) || (foo_Untyped != null)) { + "Either foo or foo_Untyped must be set, one of them is required" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + foo?.let { "foo" to it.toString() }, + foo_Untyped?.let { "foo" to it }, + bar_Untyped?.let { "bar" to it }, + "baz" to baz_Untyped, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithPartlyTypingsBindingV2 + return foo == other.foo && + foo_Untyped == other.foo_Untyped && + bar_Untyped == other.bar_Untyped && + baz_Untyped == other.baz_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + foo, + foo_Untyped, + bar_Untyped, + baz_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithPartlyTypingsBindingV2(") + append("""foo=$foo""") + append(", ") + append("""foo_Untyped=$foo_Untyped""") + append(", ") + append("""bar_Untyped=$bar_Untyped""") + append(", ") + append("""baz_Untyped=$baz_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param foo <required> + * @param foo_Untyped <required> + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + foo: Int? = this.foo, + foo_Untyped: String? = this.foo_Untyped, + bar_Untyped: String? = this.bar_Untyped, + baz_Untyped: String = this.baz_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithPartlyTypingsBindingV2 = ActionWithPartlyTypingsBindingV2( + foo = foo, + foo_Untyped = foo_Untyped, + bar_Untyped = bar_Untyped, + baz_Untyped = baz_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2_Untyped.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2_Untyped.kt new file mode 100644 index 0000000000..22ab509791 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithPartlyTypingsBindingV2_Untyped.kt @@ -0,0 +1,154 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress( + "UNUSED_PARAMETER", + "DEPRECATION", +) + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Deprecated +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * ```text + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!! WARNING !!! + * !!! !!! + * !!! This action binding has no typings provided. All inputs will !!! + * !!! have a default type of String. !!! + * !!! To be able to use this action in a type-safe way, ask the !!! + * !!! action's owner to provide the typings using !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing !!! + * !!! !!! + * !!! or if it's impossible, contribute typings to a community-driven !!! + * !!! !!! + * !!! https://github.com/typesafegithub/github-actions-typing-catalog !!! + * !!! !!! + * !!! This '_Untyped' binding will be available even once the typings !!! + * !!! are added. !!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ``` + * + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-partly-typings-binding-v2) + * + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +@Deprecated( + "Use the typed class instead", + ReplaceWith("ActionWithPartlyTypingsBindingV2"), +) +public class ActionWithPartlyTypingsBindingV2_Untyped( + vararg pleaseUseNamedArguments: Unit, + public val foo_Untyped: String, + public val bar_Untyped: String? = null, + public val baz_Untyped: String, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-partly-typings-binding-v2", + _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-partly-typings-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-partly-typings-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + "foo" to foo_Untyped, + bar_Untyped?.let { "bar" to it }, + "baz" to baz_Untyped, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithPartlyTypingsBindingV2_Untyped + return foo_Untyped == other.foo_Untyped && + bar_Untyped == other.bar_Untyped && + baz_Untyped == other.baz_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + foo_Untyped, + bar_Untyped, + baz_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithPartlyTypingsBindingV2_Untyped(") + append("""foo_Untyped=$foo_Untyped""") + append(", ") + append("""bar_Untyped=$bar_Untyped""") + append(", ") + append("""baz_Untyped=$baz_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + foo_Untyped: String = this.foo_Untyped, + bar_Untyped: String? = this.bar_Untyped, + baz_Untyped: String = this.baz_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithPartlyTypingsBindingV2_Untyped = ActionWithPartlyTypingsBindingV2_Untyped( + foo_Untyped = foo_Untyped, + bar_Untyped = bar_Untyped, + baz_Untyped = baz_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV1.kt similarity index 97% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV1.kt index 575ca18e79..8d7004921c 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV1.kt @@ -24,7 +24,7 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/action-with-some-optional-inputs) + * [Action on GitHub](https://github.com/john-smith/action-with-some-optional-inputs-binding-v1) * * @param fooBar Required is default, default is set * @param fooBar_Untyped Required is default, default is set @@ -42,7 +42,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class ActionWithSomeOptionalInputs private constructor( +public data class ActionWithSomeOptionalInputsBindingV1 private constructor( /** * Required is default, default is set */ @@ -92,8 +92,8 @@ public data class ActionWithSomeOptionalInputs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "action-with-some-optional-inputs", _customVersion - ?: "v3") { +) : RegularAction("john-smith", "action-with-some-optional-inputs-binding-v1", + _customVersion ?: "v3") { init { require(!((fooBar != null) && (fooBar_Untyped != null))) { "Only fooBar or fooBar_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV2.kt new file mode 100644 index 0000000000..f93741d1c5 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsBindingV2.kt @@ -0,0 +1,254 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress("UNUSED_PARAMETER") + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on GitHub](https://github.com/john-smith/action-with-some-optional-inputs-binding-v2) + * + * @param fooBar Required is default, default is set + * @param fooBar_Untyped Required is default, default is set + * @param bazGoo Required is default, default is null + * @param bazGoo_Untyped Required is default, default is null + * @param zooDar Required is false, default is set + * @param zooDar_Untyped Required is false, default is set + * @param cooPoo Required is false, default is default + * @param cooPoo_Untyped Required is false, default is default + * @param package <required> Required is true, default is default + * @param package_Untyped <required> Required is true, default is default + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class ActionWithSomeOptionalInputsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * Required is default, default is set + */ + public val fooBar: String? = null, + /** + * Required is default, default is set + */ + public val fooBar_Untyped: String? = null, + /** + * Required is default, default is null + */ + public val bazGoo: String? = null, + /** + * Required is default, default is null + */ + public val bazGoo_Untyped: String? = null, + /** + * Required is false, default is set + */ + public val zooDar: String? = null, + /** + * Required is false, default is set + */ + public val zooDar_Untyped: String? = null, + /** + * Required is false, default is default + */ + public val cooPoo: String? = null, + /** + * Required is false, default is default + */ + public val cooPoo_Untyped: String? = null, + /** + * <required> Required is true, default is default + */ + public val `package`: String? = null, + /** + * <required> Required is true, default is default + */ + public val package_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", "action-with-some-optional-inputs-binding-v2", + _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/action-with-some-optional-inputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/action-with-some-optional-inputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooBar != null) && (fooBar_Untyped != null))) { + "Only fooBar or fooBar_Untyped must be set, but not both" + } + + require(!((bazGoo != null) && (bazGoo_Untyped != null))) { + "Only bazGoo or bazGoo_Untyped must be set, but not both" + } + + require(!((zooDar != null) && (zooDar_Untyped != null))) { + "Only zooDar or zooDar_Untyped must be set, but not both" + } + + require(!((cooPoo != null) && (cooPoo_Untyped != null))) { + "Only cooPoo or cooPoo_Untyped must be set, but not both" + } + + require(!((`package` != null) && (package_Untyped != null))) { + "Only package or package_Untyped must be set, but not both" + } + require((`package` != null) || (package_Untyped != null)) { + "Either package or package_Untyped must be set, one of them is required" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooBar?.let { "foo-bar" to it }, + fooBar_Untyped?.let { "foo-bar" to it }, + bazGoo?.let { "baz-goo" to it }, + bazGoo_Untyped?.let { "baz-goo" to it }, + zooDar?.let { "zoo-dar" to it }, + zooDar_Untyped?.let { "zoo-dar" to it }, + cooPoo?.let { "coo-poo" to it }, + cooPoo_Untyped?.let { "coo-poo" to it }, + `package`?.let { "package" to it }, + package_Untyped?.let { "package" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as ActionWithSomeOptionalInputsBindingV2 + return fooBar == other.fooBar && + fooBar_Untyped == other.fooBar_Untyped && + bazGoo == other.bazGoo && + bazGoo_Untyped == other.bazGoo_Untyped && + zooDar == other.zooDar && + zooDar_Untyped == other.zooDar_Untyped && + cooPoo == other.cooPoo && + cooPoo_Untyped == other.cooPoo_Untyped && + `package` == other.`package` && + package_Untyped == other.package_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar, + fooBar_Untyped, + bazGoo, + bazGoo_Untyped, + zooDar, + zooDar_Untyped, + cooPoo, + cooPoo_Untyped, + `package`, + package_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("ActionWithSomeOptionalInputsBindingV2(") + append("""fooBar=$fooBar""") + append(", ") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""bazGoo=$bazGoo""") + append(", ") + append("""bazGoo_Untyped=$bazGoo_Untyped""") + append(", ") + append("""zooDar=$zooDar""") + append(", ") + append("""zooDar_Untyped=$zooDar_Untyped""") + append(", ") + append("""cooPoo=$cooPoo""") + append(", ") + append("""cooPoo_Untyped=$cooPoo_Untyped""") + append(", ") + append("""package=$`package`""") + append(", ") + append("""package_Untyped=$package_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar Required is default, default is set + * @param fooBar_Untyped Required is default, default is set + * @param bazGoo Required is default, default is null + * @param bazGoo_Untyped Required is default, default is null + * @param zooDar Required is false, default is set + * @param zooDar_Untyped Required is false, default is set + * @param cooPoo Required is false, default is default + * @param cooPoo_Untyped Required is false, default is default + * @param package <required> Required is true, default is default + * @param package_Untyped <required> Required is true, default is default + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar: String? = this.fooBar, + fooBar_Untyped: String? = this.fooBar_Untyped, + bazGoo: String? = this.bazGoo, + bazGoo_Untyped: String? = this.bazGoo_Untyped, + zooDar: String? = this.zooDar, + zooDar_Untyped: String? = this.zooDar_Untyped, + cooPoo: String? = this.cooPoo, + cooPoo_Untyped: String? = this.cooPoo_Untyped, + `package`: String? = this.`package`, + package_Untyped: String? = this.package_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): ActionWithSomeOptionalInputsBindingV2 = ActionWithSomeOptionalInputsBindingV2( + fooBar = fooBar, + fooBar_Untyped = fooBar_Untyped, + bazGoo = bazGoo, + bazGoo_Untyped = bazGoo_Untyped, + zooDar = zooDar, + zooDar_Untyped = zooDar_Untyped, + cooPoo = cooPoo, + cooPoo_Untyped = cooPoo_Untyped, + `package` = `package`, + package_Untyped = package_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsTest.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsTest.kt index eeafee18be..7906f86eff 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsTest.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/ActionWithSomeOptionalInputsTest.kt @@ -1,24 +1,32 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.bindingsfromunittests -import io.github.typesafegithub.workflows.actions.johnsmith.ActionWithSomeOptionalInputs +import io.github.typesafegithub.workflows.actionbindinggenerator.constructAction +import io.github.typesafegithub.workflows.actionbindinggenerator.withAllBindingVersions import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe class ActionWithSomeOptionalInputsTest : DescribeSpec({ - it("renders with defaults") { - // given - val action = ActionWithSomeOptionalInputs( - bazGoo = "def456", - `package` = "qwe789" - ) + context("renders with defaults") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "ActionWithSomeOptionalInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "bazGoo" to "def456", + "package" to "qwe789", + ), + ) - // when - val yaml = action.toYamlArguments() + // when + val yaml = action.toYamlArguments() - // then - yaml shouldBe linkedMapOf( - "baz-goo" to "def456", - "package" to "qwe789", - ) + // then + yaml shouldBe linkedMapOf( + "baz-goo" to "def456", + "package" to "qwe789", + ) + } } }) diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputs.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV1.kt similarity index 92% rename from action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputs.kt rename to action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV1.kt index a45eb562e8..867c1b9d58 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputs.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV1.kt @@ -27,7 +27,8 @@ import kotlin.collections.toTypedArray * * This is a test description that should be put in the KDoc comment for a class * - * [Action on GitHub](https://github.com/john-smith/simple-action-with-required-string-inputs) + * [Action on + * GitHub](https://github.com/john-smith/simple-action-with-required-string-inputs-binding-v1) * * @param fooBar <required> Short description * @param fooBar_Untyped <required> Short description @@ -41,7 +42,7 @@ import kotlin.collections.toTypedArray * version, or a newer version that the binding doesn't yet know about */ @ExposedCopyVisibility -public data class SimpleActionWithRequiredStringInputs private constructor( +public data class SimpleActionWithRequiredStringInputsBindingV1 private constructor( /** * <required> Short description */ @@ -71,8 +72,8 @@ public data class SimpleActionWithRequiredStringInputs private constructor( * version that the binding doesn't yet know about */ public val _customVersion: String? = null, -) : RegularAction("john-smith", "simple-action-with-required-string-inputs", - _customVersion ?: "v3") { +) : RegularAction("john-smith", + "simple-action-with-required-string-inputs-binding-v1", _customVersion ?: "v3") { init { require(!((fooBar != null) && (fooBar_Untyped != null))) { "Only fooBar or fooBar_Untyped must be set, but not both" diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV2.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV2.kt new file mode 100644 index 0000000000..024060e4c5 --- /dev/null +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsBindingV2.kt @@ -0,0 +1,182 @@ +// This file was generated using action-binding-generator. Don't change it by hand, otherwise your +// changes will be overwritten with the next binding code regeneration. +// See https://github.com/typesafegithub/github-workflows-kt for more info. +@file:Suppress( + "UNUSED_PARAMETER", + "DEPRECATION", +) + +package io.github.typesafegithub.workflows.actions.johnsmith + +import io.github.typesafegithub.workflows.domain.actions.Action +import io.github.typesafegithub.workflows.domain.actions.RegularAction +import java.util.LinkedHashMap +import java.util.Objects +import kotlin.Any +import kotlin.Boolean +import kotlin.Deprecated +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.Map +import kotlin.collections.toList +import kotlin.collections.toTypedArray + +/** + * Action: Do something cool + * and describe it in multiple lines + * + * This is a test description that should be put in the KDoc comment for a class + * + * [Action on + * GitHub](https://github.com/john-smith/simple-action-with-required-string-inputs-binding-v2) + * + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param bazGoo <required> Just another input + * with multiline description + * @param bazGoo_Untyped <required> Just another input + * with multiline description + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by + * the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ +public class SimpleActionWithRequiredStringInputsBindingV2( + vararg pleaseUseNamedArguments: Unit, + /** + * <required> Short description + */ + public val fooBar: String? = null, + /** + * <required> Short description + */ + public val fooBar_Untyped: String? = null, + /** + * <required> Just another input + * with multiline description + */ + @Deprecated("this is deprecated") + public val bazGoo: String? = null, + /** + * <required> Just another input + * with multiline description + */ + @Deprecated("this is deprecated") + public val bazGoo_Untyped: String? = null, + /** + * Type-unsafe map where you can put any inputs that are not yet supported by the binding + */ + public val _customInputs: Map = mapOf(), + /** + * Allows overriding action's version, for example to use a specific minor version, or a newer + * version that the binding doesn't yet know about + */ + public val _customVersion: String? = null, +) : RegularAction("john-smith", + "simple-action-with-required-string-inputs-binding-v2", _customVersion ?: "v3") { + init { + println("WARNING: The used binding version v2 for john-smith/simple-action-with-required-string-inputs-binding-v2@v3 is experimental! Last stable version is v1.") + if (System.getenv("GITHUB_ACTIONS").toBoolean()) { + println(""" + | + |::warning title=Experimental Binding Version Used::The used binding version v2 for john-smith/simple-action-with-required-string-inputs-binding-v2@v3 is experimental! Last stable version is v1. + """.trimMargin()) + } + + require(!((fooBar != null) && (fooBar_Untyped != null))) { + "Only fooBar or fooBar_Untyped must be set, but not both" + } + require((fooBar != null) || (fooBar_Untyped != null)) { + "Either fooBar or fooBar_Untyped must be set, one of them is required" + } + + require(!((bazGoo != null) && (bazGoo_Untyped != null))) { + "Only bazGoo or bazGoo_Untyped must be set, but not both" + } + require((bazGoo != null) || (bazGoo_Untyped != null)) { + "Either bazGoo or bazGoo_Untyped must be set, one of them is required" + } + } + + @Suppress("SpreadOperator") + override fun toYamlArguments(): LinkedHashMap = linkedMapOf( + *listOfNotNull( + fooBar?.let { "foo-bar" to it }, + fooBar_Untyped?.let { "foo-bar" to it }, + bazGoo?.let { "baz-goo" to it }, + bazGoo_Untyped?.let { "baz-goo" to it }, + *_customInputs.toList().toTypedArray(), + ).toTypedArray() + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as SimpleActionWithRequiredStringInputsBindingV2 + return fooBar == other.fooBar && + fooBar_Untyped == other.fooBar_Untyped && + bazGoo == other.bazGoo && + bazGoo_Untyped == other.bazGoo_Untyped && + _customInputs == other._customInputs && + _customVersion == other._customVersion + } + + override fun hashCode(): Int = Objects.hash( + fooBar, + fooBar_Untyped, + bazGoo, + bazGoo_Untyped, + _customInputs, + _customVersion, + ) + + override fun toString(): String = buildString { + append("SimpleActionWithRequiredStringInputsBindingV2(") + append("""fooBar=$fooBar""") + append(", ") + append("""fooBar_Untyped=$fooBar_Untyped""") + append(", ") + append("""bazGoo=$bazGoo""") + append(", ") + append("""bazGoo_Untyped=$bazGoo_Untyped""") + append(", ") + append("""_customInputs=$_customInputs""") + append(", ") + append("""_customVersion=$_customVersion""") + append(")") + } + + /** + * @param fooBar <required> Short description + * @param fooBar_Untyped <required> Short description + * @param bazGoo <required> Just another input + * with multiline description + * @param bazGoo_Untyped <required> Just another input + * with multiline description + * @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported + * by the binding + * @param _customVersion Allows overriding action's version, for example to use a specific minor + * version, or a newer version that the binding doesn't yet know about + */ + public fun copy( + vararg pleaseUseNamedArguments: Unit, + fooBar: String? = this.fooBar, + fooBar_Untyped: String? = this.fooBar_Untyped, + bazGoo: String? = this.bazGoo, + bazGoo_Untyped: String? = this.bazGoo_Untyped, + _customInputs: Map = this._customInputs, + _customVersion: String? = this._customVersion, + ): SimpleActionWithRequiredStringInputsBindingV2 = + SimpleActionWithRequiredStringInputsBindingV2( + fooBar = fooBar, + fooBar_Untyped = fooBar_Untyped, + bazGoo = bazGoo, + bazGoo_Untyped = bazGoo_Untyped, + _customInputs = _customInputs, + _customVersion = _customVersion, + ) + + override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId) +} diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsTest.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsTest.kt index 598972405c..c487034cfb 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsTest.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/bindingsfromunittests/SimpleActionWithRequiredStringInputsTest.kt @@ -1,24 +1,32 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.bindingsfromunittests -import io.github.typesafegithub.workflows.actions.johnsmith.SimpleActionWithRequiredStringInputs +import io.github.typesafegithub.workflows.actionbindinggenerator.constructAction +import io.github.typesafegithub.workflows.actionbindinggenerator.withAllBindingVersions import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe class SimpleActionWithRequiredStringInputsTest : DescribeSpec({ - it("renders with defaults") { - // given - val action = SimpleActionWithRequiredStringInputs( - fooBar = "abc123", - bazGoo = "def456", - ) + context("renders with defaults") { + withAllBindingVersions { bindingVersion -> + // given + val action = constructAction( + owner = "johnsmith", + classBaseName = "SimpleActionWithRequiredStringInputs", + bindingVersion = bindingVersion, + arguments = mapOf( + "fooBar" to "abc123", + "bazGoo" to "def456", + ), + ) - // when - val yaml = action.toYamlArguments() + // when + val yaml = action.toYamlArguments() - // then - yaml shouldBe linkedMapOf( - "foo-bar" to "abc123", - "baz-goo" to "def456", - ) + // then + yaml shouldBe linkedMapOf( + "foo-bar" to "abc123", + "baz-goo" to "def456", + ) + } } }) diff --git a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/GenerationTest.kt b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/GenerationTest.kt index 4e08800962..8f1922d3fb 100644 --- a/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/GenerationTest.kt +++ b/action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/GenerationTest.kt @@ -16,6 +16,7 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.typing.IntegerW import io.github.typesafegithub.workflows.actionbindinggenerator.typing.ListOfTypings import io.github.typesafegithub.workflows.actionbindinggenerator.typing.StringTyping import io.github.typesafegithub.workflows.actionbindinggenerator.typing.Typing +import io.github.typesafegithub.workflows.actionbindinggenerator.withAllBindingVersions import io.kotest.assertions.assertSoftly import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.collections.shouldHaveSize @@ -110,373 +111,403 @@ class GenerationTest : ), ) - test("action with required inputs as strings, no outputs") { - // given - val actionManifest = - Metadata( - name = - """ - Do something cool - and describe it in multiple lines - """.trimIndent(), - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo-bar" to - Input( - description = "Short description", - required = true, - default = null, - ), - "baz-goo" to - Input( - description = - """ - Just another input - with multiline description - """.trimIndent(), - deprecationMessage = "this is deprecated", - required = true, - default = null, - ), - ), - ) - val coords = ActionCoords("john-smith", "simple-action-with-required-string-inputs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("SimpleActionWithRequiredStringInputs.kt") + context("action with required inputs as strings, no outputs") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = + """ + Do something cool + and describe it in multiple lines + """.trimIndent(), + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "foo-bar" to + Input( + description = "Short description", + required = true, + default = null, + ), + "baz-goo" to + Input( + description = + """ + Just another input + with multiline description + """.trimIndent(), + deprecationMessage = "this is deprecated", + required = true, + default = null, + ), + ), + ) + val coords = ActionCoords("john-smith", "simple-action-with-required-string-inputs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("SimpleActionWithRequiredStringInputsBinding${bindingVersion.name}.kt") + } } - test("action with various combinations of input parameters describing being required or optional") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo-bar" to - Input( - description = "Required is default, default is set", - default = "barfoo", - ), - "baz-goo" to - Input( - description = "Required is default, default is null", - default = null, - ), - "zoo-dar" to - Input( - description = "Required is false, default is set", - required = false, - default = "googoo", - ), - "coo-poo" to - Input( - description = "Required is false, default is default", - required = false, - ), - "package" to - Input( - description = "Required is true, default is default", - required = true, - ), - ), - ) - val coords = ActionCoords("john-smith", "action-with-some-optional-inputs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("ActionWithSomeOptionalInputs.kt") + context("action with various combinations of input parameters describing being required or optional") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "foo-bar" to + Input( + description = "Required is default, default is set", + default = "barfoo", + ), + "baz-goo" to + Input( + description = "Required is default, default is null", + default = null, + ), + "zoo-dar" to + Input( + description = "Required is false, default is set", + required = false, + default = "googoo", + ), + "coo-poo" to + Input( + description = "Required is false, default is default", + required = false, + ), + "package" to + Input( + description = "Required is true, default is default", + required = true, + ), + ), + ) + val coords = ActionCoords("john-smith", "action-with-some-optional-inputs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("ActionWithSomeOptionalInputsBinding${bindingVersion.name}.kt") + } } - test("action with all types of inputs") { - // given - val coords = ActionCoords("john-smith", "action-with-all-types-of-inputs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifestWithAllTypesOfInputsAndSomeOutput, - inputTypings = - Pair( - typingsForAllTypesOfInputs, - ACTION, - ), - ) - - // then - assertSoftly { - binding.shouldContainAndMatchFile("ActionWithAllTypesOfInputs.kt") - binding.shouldContainAndMatchFile("ActionWithAllTypesOfInputs_Untyped.kt") + context("action with all types of inputs") { + withAllBindingVersions { bindingVersion -> + // given + val coords = ActionCoords("john-smith", "action-with-all-types-of-inputs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifestWithAllTypesOfInputsAndSomeOutput, + inputTypings = + Pair( + typingsForAllTypesOfInputs, + ACTION, + ), + ) + + // then + assertSoftly { + binding.shouldContainAndMatchFile("ActionWithAllTypesOfInputsBinding${bindingVersion.name}.kt") + binding.shouldContainAndMatchFile("ActionWithAllTypesOfInputsBinding${bindingVersion.name}_Untyped.kt") + } } } - test("action with outputs") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo-bar" to - Input( - description = "Short description", - required = true, - default = null, - ), - ), - outputs = - mapOf( - "baz-goo" to Output(description = "Cool output!"), - "loo-woz" to Output(description = "Another output..."), - ), - ) - val coords = ActionCoords("john-smith", "action-with-outputs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("ActionWithOutputs.kt") + context("action with outputs") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "foo-bar" to + Input( + description = "Short description", + required = true, + default = null, + ), + ), + outputs = + mapOf( + "baz-goo" to Output(description = "Cool output!"), + "loo-woz" to Output(description = "Another output..."), + ), + ) + val coords = ActionCoords("john-smith", "action-with-outputs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("ActionWithOutputsBinding${bindingVersion.name}.kt") + } } - test("action with no inputs") { - // given - val actionManifestHasNoInputs = emptyMap() - val actionManifest = - Metadata( - inputs = actionManifestHasNoInputs, - name = "Action With No Inputs", - description = "Description", - ) - - val coords = ActionCoords("john-smith", "action-with-no-inputs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(emptyMap(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("ActionWithNoInputs.kt") + context("action with no inputs") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifestHasNoInputs = emptyMap() + val actionManifest = + Metadata( + inputs = actionManifestHasNoInputs, + name = "Action With No Inputs", + description = "Description", + ) + + val coords = ActionCoords("john-smith", "action-with-no-inputs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(emptyMap(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("ActionWithNoInputsBinding${bindingVersion.name}.kt") + } } - test("action with deprecated input resolving to the same Kotlin field name") { - // given - val actionManifest = - Metadata( - inputs = - mapOf( - "foo-bar" to - Input( - description = "Foo bar - old", - required = true, - default = null, - deprecationMessage = "Use 'fooBar'!", - ), - "fooBar" to - Input( - description = "Foo bar - new", - required = true, - default = null, - ), - ), - name = "Some Action", - description = "Description", - ) - - val coords = ActionCoords("john-smith", "action-with-deprecated-input-and-name-clash", "v2") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("ActionWithDeprecatedInputAndNameClash.kt") + context("action with deprecated input resolving to the same Kotlin field name") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + inputs = + mapOf( + "foo-bar" to + Input( + description = "Foo bar - old", + required = true, + default = null, + deprecationMessage = "Use 'fooBar'!", + ), + "fooBar" to + Input( + description = "Foo bar - new", + required = true, + default = null, + ), + ), + name = "Some Action", + description = "Description", + ) + + val coords = ActionCoords("john-smith", "action-with-deprecated-input-and-name-clash-binding-$bindingVersion", "v2") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("ActionWithDeprecatedInputAndNameClashBinding${bindingVersion.name}.kt") + } } - test("action with inputs sharing type") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo-one" to - Input( - required = true, - default = null, - ), - "foo-two" to - Input( - required = true, - default = null, - ), - "foo-three" to - Input( - required = false, - default = "test", - ), - ), - ) - val coords = ActionCoords("john-smith", "action-with-inputs-sharing-type", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = - Pair( + context("action with inputs sharing type") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = mapOf( - "foo-one" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), - "foo-two" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), - "foo-three" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), + "foo-one" to + Input( + required = true, + default = null, + ), + "foo-two" to + Input( + required = true, + default = null, + ), + "foo-three" to + Input( + required = false, + default = "test", + ), ), - ACTION, - ), - ) + ) + val coords = ActionCoords("john-smith", "action-with-inputs-sharing-type-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = + Pair( + mapOf( + "foo-one" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), + "foo-two" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), + "foo-three" to IntegerWithSpecialValueTyping("Foo", mapOf("Special1" to 3)), + ), + ACTION, + ), + ) - // then - binding.shouldContainAndMatchFile("ActionWithInputsSharingType.kt") + // then + binding.shouldContainAndMatchFile("ActionWithInputsSharingTypeBinding${bindingVersion.name}.kt") + } } - test("action with input descriptions with fancy characters") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "nested-kotlin-comments" to - Input( - description = "This is a /* test */", - ), - "percent" to - Input( - description = "For example \"100%\"", - ), - ), - ) - val coords = ActionCoords("john-smith", "action-with-fancy-chars-in-docs", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), - ) - - // then - binding.shouldContainAndMatchFile("ActionWithFancyCharsInDocs.kt") + context("action with input descriptions with fancy characters") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "nested-kotlin-comments" to + Input( + description = "This is a /* test */", + ), + "percent" to + Input( + description = "For example \"100%\"", + ), + ), + ) + val coords = ActionCoords("john-smith", "action-with-fancy-chars-in-docs-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(actionManifest.allInputsAsStrings(), ACTION), + ) + + // then + binding.shouldContainAndMatchFile("ActionWithFancyCharsInDocsBinding${bindingVersion.name}.kt") + } } - test("action with no typings has only an untyped binding") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo" to - Input( - required = true, - default = null, - ), - "bar" to - Input( - required = false, - default = "test", - ), - ), - ) - val coords = ActionCoords("john-smith", "action-with-no-typings", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(emptyMap(), null), - ) - - // then - binding shouldHaveSize 1 - binding.shouldContainAndMatchFile("ActionWithNoTypings_Untyped.kt") + context("action with no typings has only an untyped binding") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "foo" to + Input( + required = true, + default = null, + ), + "bar" to + Input( + required = false, + default = "test", + ), + ), + ) + val coords = ActionCoords("john-smith", "action-with-no-typings-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(emptyMap(), null), + ) + + // then + binding shouldHaveSize 1 + binding.shouldContainAndMatchFile("ActionWithNoTypingsBinding${bindingVersion.name}_Untyped.kt") + } } - test("action with partly typings has only untyped properties for the non-typed inputs") { - // given - val actionManifest = - Metadata( - name = "Do something cool", - description = "This is a test description that should be put in the KDoc comment for a class", - inputs = - mapOf( - "foo" to - Input( - required = true, - default = null, - ), - "bar" to - Input( - required = false, - default = "test", - ), - "baz" to - Input( - required = true, - ), - ), - ) - val coords = ActionCoords("john-smith", "action-with-partly-typings", "v3") - - // when - val binding = - coords.generateBinding( - metadataRevision = NewestForVersion, - metadata = actionManifest, - inputTypings = Pair(mapOf("foo" to IntegerTyping), TYPING_CATALOG), - ) - - // then - assertSoftly { - binding.shouldContainAndMatchFile("ActionWithPartlyTypings.kt") - binding.shouldContainAndMatchFile("ActionWithPartlyTypings_Untyped.kt") + context("action with partly typings has only untyped properties for the non-typed inputs") { + withAllBindingVersions { bindingVersion -> + // given + val actionManifest = + Metadata( + name = "Do something cool", + description = "This is a test description that should be put in the KDoc comment for a class", + inputs = + mapOf( + "foo" to + Input( + required = true, + default = null, + ), + "bar" to + Input( + required = false, + default = "test", + ), + "baz" to + Input( + required = true, + ), + ), + ) + val coords = ActionCoords("john-smith", "action-with-partly-typings-binding-$bindingVersion", "v3") + + // when + val binding = + coords.generateBinding( + bindingVersion = bindingVersion, + metadataRevision = NewestForVersion, + metadata = actionManifest, + inputTypings = Pair(mapOf("foo" to IntegerTyping), TYPING_CATALOG), + ) + + // then + assertSoftly { + binding.shouldContainAndMatchFile("ActionWithPartlyTypingsBinding${bindingVersion.name}.kt") + binding.shouldContainAndMatchFile("ActionWithPartlyTypingsBinding${bindingVersion.name}_Untyped.kt") + } } } }) diff --git a/docs/user-guide/using-actions.md b/docs/user-guide/using-actions.md index c1828fb59f..b1e0ade60d 100644 --- a/docs/user-guide/using-actions.md +++ b/docs/user-guide/using-actions.md @@ -46,6 +46,92 @@ as it could still make sense to use them, for example if you want to set the val This approach supports dependency updating bots that support Kotlin Script's `.main.kts` files. E.g. Renovate is known to support it. +### Binary compatibility of generated bindings + +The generated bindings are not guaranteed to be binary compatible. As soon as an action owner for example adds a +new input, the signature of the constructor changes and the signature of the `copy` method of that action's binding +changes. So you should not use these generated bindings in any pre-compiled code, unless you are pretty sure you +know what you are doing and are aware of the consequences. + +The typical usage of the generated bindings are not affected by this. By technically enforcing the usage of named +arguments when using the constructor or `copy` method, the bindings stay source compatible even if new inputs are +added. So if you are just using the bindings within `.main.kts` scripts for which they are designed, you are safe. +The only exception is, when an action owner removes or renames an input. But according to semver, this is a breaking +change and an action author should not do this within the same major version. If he nevertheless did, open a bug +issue in that action's GitHub repository so the owner can revert the change and instead release a new major version. + +### Available repository URL + +Evolving this library and / or the generated bindings sometimes requires breaking changes in the generated bindings. +To not break your existing workflow scripts, the bindings delivered on a given repository URL should always stay +backwards compatible (in terms of source compatibility). If accidentally a breaking change was done on given repository +URL, please open a bug report. Unless very good reasons object, the change will be reverted and instead be done on +a different repository URL. Such a situation is usually indicated by your workflow scripts suddenly failing to execute +without you having done any changes to it, except if the breaking change is caused by an action author doing a breaking +change inappropriately. In that case, please open a bug report with that action's GitHub repository instead. + +#### Stability statuses + +*Experimental* + +: If a new repository URL is added, it will initially be in experimental state. When using such a URL, you get the + cutting edge changes, but no stability is guaranteed. Any breaking change can happen at any time, so use these URL + only if you have that in mind and consent to the consequences. Executing a workflow script with such a repository + URL will issue a warning and executing it on GitHub Actions will add a warning annotation to the workflow run. + +*Stable* + +: Repository URL that are in stable state will not have any source incompatible changes done. There will typically + only be one stable URL, and that is what you should usually use in your workflow scripts. + +*Deprecated* + +: Upon new stable URL becoming available, existing stable URL will most probably be moved to deprecated state. + Deprecated state for now does not mean, that the repository URL will be turned off. On a deprecated URL also no + source incompatible changes will be done, but new changes might not be added to the deprecated URL. The main + intention of deprecating a URL is to hint at newer stable URL being available. For this all bindings generated + on this URL will be marked as `@Deprecated` and executing the workflow script will issue a warning and if run + on GitHub Actions will add a warning annotation to the workflow run. + +| Repository URL | Stability | +|-------------------------------------|-----------------------------------------------------------------------| +| `https://bindings.krzeminski.it` | :material-check-bold:{ style="color: green" } stable (alias for `/v1`) | +| `https://bindings.krzeminski.it/v1` | :material-check-bold:{ style="color: green" } stable | +| `https://bindings.krzeminski.it/v2` | :no_entry: experimental | + +#### Library version compatibility + +As the library and / or generated bindings evolve, not all library versions will be compatible with all repository URL. +This table lists which library versions are compatible with which repository URL. + +| Repository URL | Compatibility | +|-------------------------------------|-------------------| +| `https://bindings.krzeminski.it` | `3.0.0` and newer | +| `https://bindings.krzeminski.it/v1` | `3.0.0` and newer | +| `https://bindings.krzeminski.it/v2` | `3.0.0` and newer | + +#### Breaking changes + +This section shows which source incompatible breaking changes were done in each repository URL. When changing +from a previous URL to a later one, these might be issues you are hitting and need to adapt to in your workflow +scripts. Binary breaking changes are not listed here, as binary compatibility is not guaranteed +anyway as defined above. + +`https://bindings.krzeminski.it/v2` + +: - Binding classes are no `data` classes anymore. + - The `equals` method will work like before. + - The `hashCode` method will work like before. + - The `toString` method will work like before. + - Destructuring assignments are not possible anymore as this will likely break silently or during + compilation when action owners add new inputs in between existing ones. + - The `clone` method will work like before, just that now usage of named arguments is enforced + to ensure source compatibility when action owners add new inputs in between existing ones. + +`https://bindings.krzeminski.it` / `https://bindings.krzeminski.it/v1` + +: This is the original `v1` URL with which generated bindings have started. + ## User-defined actions If you are in a hurry and adding typings is not possible right now, browse these options. diff --git a/mkdocs.yml b/mkdocs.yml index 1492f9b592..64b63042ea 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,6 +33,11 @@ markdown_extensions: check_paths: True dedent_subsections: True - admonition + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - def_list + - attr_list plugins: - search