Skip to content

Commit 2c8968b

Browse files
committed
feat(abg): support different binding versions on different server routes
1 parent 83fdeeb commit 2c8968b

File tree

10 files changed

+224
-31
lines changed

10 files changed

+224
-31
lines changed

.github/workflows/bindings-server.main.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ workflow(
9090

9191
cleanMavenLocal()
9292

93+
run(
94+
name = "Execute the script using the bindings from the server with v1 route",
95+
command = """
96+
mv .github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts .github/workflows/test-script-consuming-jit-bindings-v1.main.kts
97+
.github/workflows/test-script-consuming-jit-bindings-v1.main.kts
98+
""".trimIndent(),
99+
)
100+
101+
cleanMavenLocal()
102+
93103
run(
94104
name = "Execute the script using bindings but without dependency on library",
95105
command = """

.github/workflows/bindings-server.yaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,22 @@ jobs:
5555
name: 'Clean Maven Local to fetch required POMs again'
5656
run: 'rm -rf ~/.m2/repository/'
5757
- id: 'step-7'
58+
name: 'Execute the script using the bindings from the server with v1 route'
59+
run: |-
60+
mv .github/workflows/test-script-consuming-jit-bindings-v1.main.do-not-compile.kts .github/workflows/test-script-consuming-jit-bindings-v1.main.kts
61+
.github/workflows/test-script-consuming-jit-bindings-v1.main.kts
62+
- id: 'step-8'
63+
name: 'Clean Maven Local to fetch required POMs again'
64+
run: 'rm -rf ~/.m2/repository/'
65+
- id: 'step-9'
5866
name: 'Execute the script using bindings but without dependency on library'
5967
run: |-
6068
mv .github/workflows/test-served-bindings-depend-on-library.main.do-not-compile.kts .github/workflows/test-served-bindings-depend-on-library.main.kts
6169
.github/workflows/test-served-bindings-depend-on-library.main.kts
62-
- id: 'step-8'
70+
- id: 'step-10'
6371
name: 'Fetch maven-metadata.xml for top-level action'
6472
run: 'curl --fail http://localhost:8080/actions/checkout/maven-metadata.xml | grep ''<version>v4</version>'''
65-
- id: 'step-9'
73+
- id: 'step-11'
6674
name: 'Fetch maven-metadata.xml for nested action'
6775
run: 'curl --fail http://localhost:8080/actions/cache__save/maven-metadata.xml | grep ''<version>v4</version>'''
6876
deploy:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env kotlin
2+
@file:Repository("https://repo.maven.apache.org/maven2/")
3+
@file:DependsOn("io.github.typesafegithub:github-workflows-kt:1.13.0")
4+
5+
@file:Repository("http://localhost:8080/v1")
6+
7+
// Regular, top-level action.
8+
@file:DependsOn("actions:checkout:v4")
9+
10+
// Nested action.
11+
@file:DependsOn("gradle:actions__setup-gradle:v3")
12+
13+
// Using specific version.
14+
@file:DependsOn("actions:cache:v3.3.3")
15+
16+
// Always untyped action.
17+
@file:DependsOn("typesafegithub:always-untyped-action-for-tests:v1")
18+
19+
import io.github.typesafegithub.workflows.actions.actions.Cache
20+
import io.github.typesafegithub.workflows.actions.actions.Checkout
21+
import io.github.typesafegithub.workflows.actions.actions.Checkout_Untyped
22+
import io.github.typesafegithub.workflows.actions.gradle.ActionsSetupGradle
23+
import io.github.typesafegithub.workflows.actions.typesafegithub.AlwaysUntypedActionForTests_Untyped
24+
25+
println(Checkout_Untyped(fetchTags_Untyped = "false"))
26+
println(Checkout(fetchTags = false))
27+
println(Checkout(fetchTags_Untyped = "false"))
28+
println(AlwaysUntypedActionForTests_Untyped(foobar_Untyped = "baz"))
29+
println(ActionsSetupGradle())
30+
println(Cache(path = listOf("some-path"), key = "some-key"))
31+
32+
// Ensure that 'copy(...)' method is exposed.
33+
Checkout(fetchTags = false).copy(fetchTags = true)

action-binding-generator/api/action-binding-generator.api

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public final class io/github/typesafegithub/workflows/actionbindinggenerator/gen
6969
}
7070

7171
public final class io/github/typesafegithub/workflows/actionbindinggenerator/generation/GenerationKt {
72-
public static final fun generateBinding (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;Lkotlin/Pair;)Ljava/util/List;
73-
public static synthetic fun generateBinding$default (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;Lkotlin/Pair;ILjava/lang/Object;)Ljava/util/List;
72+
public static final fun generateBinding (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;Lkotlin/Pair;)Ljava/util/List;
73+
public static synthetic fun generateBinding$default (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;Lkotlin/Pair;ILjava/lang/Object;)Ljava/util/List;
7474
}
7575

7676
public final class io/github/typesafegithub/workflows/actionbindinggenerator/metadata/Input {
@@ -179,3 +179,14 @@ public final class io/github/typesafegithub/workflows/actionbindinggenerator/met
179179
public abstract interface class io/github/typesafegithub/workflows/actionbindinggenerator/typing/Typing {
180180
}
181181

182+
public final class io/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion : java/lang/Enum {
183+
public static final field V1 Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion;
184+
public static fun getEntries ()Lkotlin/enums/EnumEntries;
185+
public final fun getLibraryVersion ()Ljava/lang/String;
186+
public final fun isDeprecated ()Z
187+
public final fun isExperimental ()Z
188+
public fun toString ()Ljava/lang/String;
189+
public static fun valueOf (Ljava/lang/String;)Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion;
190+
public static fun values ()[Lio/github/typesafegithub/workflows/actionbindinggenerator/versioning/BindingVersion;
191+
}
192+

action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/Generation.kt

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import com.squareup.kotlinpoet.buildCodeBlock
1818
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
1919
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
2020
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource
21+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.prettyPrint
2122
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_INPUTS
2223
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_VERSION
2324
import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Input
@@ -33,6 +34,8 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.typing.provideT
3334
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.removeTrailingWhitespacesForEachLine
3435
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toCamelCase
3536
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toKotlinPackageName
37+
import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion
38+
import io.github.typesafegithub.workflows.actionbindinggenerator.versioning.BindingVersion.V1
3639

3740
public data class ActionBinding(
3841
val kotlinCode: String,
@@ -55,6 +58,7 @@ private object Properties {
5558
}
5659

5760
public fun ActionCoords.generateBinding(
61+
bindingVersion: BindingVersion = V1,
5862
metadataRevision: MetadataRevision,
5963
metadata: Metadata? = null,
6064
inputTypings: Pair<Map<String, Typing>, TypingActualSource?>? = null,
@@ -70,10 +74,11 @@ public fun ActionCoords.generateBinding(
7074

7175
val actionBindingSourceCodeUntyped =
7276
generateActionBindingSourceCode(
73-
metadataProcessed,
74-
this,
75-
emptyMap(),
76-
classNameUntyped,
77+
metadata = metadataProcessed,
78+
coords = this,
79+
bindingVersion = bindingVersion,
80+
inputTypings = emptyMap(),
81+
className = classNameUntyped,
7782
untypedClass = true,
7883
replaceWith = inputTypingsResolved.second?.let { CodeBlock.of("ReplaceWith(%S)", className) },
7984
)
@@ -91,6 +96,7 @@ public fun ActionCoords.generateBinding(
9196
generateActionBindingSourceCode(
9297
metadata = metadataProcessed,
9398
coords = this,
99+
bindingVersion = bindingVersion,
94100
inputTypings = inputTypingsResolved.first,
95101
className = className,
96102
)
@@ -121,6 +127,7 @@ private fun Metadata.removeDeprecatedInputsIfNameClash(): Metadata {
121127
private fun generateActionBindingSourceCode(
122128
metadata: Metadata,
123129
coords: ActionCoords,
130+
bindingVersion: BindingVersion,
124131
inputTypings: Map<String, Typing>,
125132
className: String,
126133
untypedClass: Boolean = false,
@@ -137,7 +144,7 @@ private fun generateActionBindingSourceCode(
137144
changes will be overwritten with the next binding code regeneration.
138145
See https://github.com/typesafegithub/github-workflows-kt for more info.
139146
""".trimIndent(),
140-
).addType(generateActionClass(metadata, coords, inputTypings, className, untypedClass, replaceWith))
147+
).addType(generateActionClass(metadata, coords, bindingVersion, inputTypings, className, untypedClass, replaceWith))
141148
.addSuppressAnnotation(metadata)
142149
.indent(" ")
143150
.build()
@@ -166,6 +173,7 @@ private fun FileSpec.Builder.addSuppressAnnotation(metadata: Metadata) =
166173
private fun generateActionClass(
167174
metadata: Metadata,
168175
coords: ActionCoords,
176+
bindingVersion: BindingVersion,
169177
inputTypings: Map<String, Typing>,
170178
className: String,
171179
untypedClass: Boolean,
@@ -175,12 +183,13 @@ private fun generateActionClass(
175183
.classBuilder(className)
176184
.addModifiers(KModifier.DATA)
177185
.addKdocIfNotEmpty(actionKdoc(metadata, coords, untypedClass))
178-
.replaceWith(replaceWith)
186+
.deprecateBindingVersion(bindingVersion)
187+
.replaceWith(bindingVersion, replaceWith)
179188
.addClassConstructorAnnotation()
180189
.inheritsFromRegularAction(coords, metadata, className)
181190
.primaryConstructor(metadata.primaryConstructor(inputTypings, coords, className, untypedClass))
182191
.properties(metadata, coords, inputTypings, className, untypedClass)
183-
.addInitializerBlockIfNecessary(metadata, inputTypings, untypedClass)
192+
.addInitializerBlock(metadata, bindingVersion, coords, inputTypings, untypedClass)
184193
.addFunction(metadata.secondaryConstructor(inputTypings, coords, className, untypedClass))
185194
.addFunction(metadata.buildToYamlArgumentsFunction(inputTypings, untypedClass))
186195
.addCustomTypes(inputTypings, coords, className)
@@ -368,8 +377,23 @@ private fun Metadata.linkedMapOfInputs(
368377
}
369378
}
370379

371-
private fun TypeSpec.Builder.replaceWith(replaceWith: CodeBlock?): TypeSpec.Builder {
372-
if (replaceWith != null) {
380+
private fun TypeSpec.Builder.deprecateBindingVersion(bindingVersion: BindingVersion): TypeSpec.Builder {
381+
if (bindingVersion.isDeprecated) {
382+
addAnnotation(
383+
AnnotationSpec
384+
.builder(Deprecated::class.asClassName())
385+
.addMember("%S", "Use a non-deprecated binding version in the repository URL")
386+
.build(),
387+
)
388+
}
389+
return this
390+
}
391+
392+
private fun TypeSpec.Builder.replaceWith(
393+
bindingVersion: BindingVersion,
394+
replaceWith: CodeBlock?,
395+
): TypeSpec.Builder {
396+
if (!bindingVersion.isDeprecated && replaceWith != null) {
373397
addAnnotation(
374398
AnnotationSpec
375399
.builder(Deprecated::class.asClassName())
@@ -528,15 +552,63 @@ private fun ParameterSpec.Builder.defaultValueIfNullable(
528552
return this
529553
}
530554

531-
private fun TypeSpec.Builder.addInitializerBlockIfNecessary(
555+
private fun TypeSpec.Builder.addInitializerBlock(
532556
metadata: Metadata,
557+
bindingVersion: BindingVersion,
558+
coords: ActionCoords,
533559
inputTypings: Map<String, Typing>,
534560
untypedClass: Boolean,
535561
): TypeSpec.Builder {
536-
if (untypedClass || metadata.inputs.isEmpty() || metadata.inputs.none { inputTypings.containsKey(it.key) }) {
562+
if (!bindingVersion.isDeprecated &&
563+
!bindingVersion.isExperimental &&
564+
(untypedClass || metadata.inputs.isEmpty() || metadata.inputs.none { inputTypings.containsKey(it.key) })
565+
) {
537566
return this
538567
}
539-
addInitializerBlock(metadata.initializerBlock(inputTypings))
568+
569+
addInitializerBlock(
570+
buildCodeBlock {
571+
if (bindingVersion.isDeprecated) {
572+
val firstStableVersion = BindingVersion.entries.find { !it.isDeprecated && !it.isExperimental }
573+
addStatement(
574+
"println(%S)",
575+
"""
576+
WARNING: The used binding version $bindingVersion for ${coords.prettyPrint} is deprecated! First stable version is $firstStableVersion.
577+
""".trimIndent(),
578+
)
579+
beginControlFlow("""if (System.getenv("GITHUB_ACTIONS").toBoolean())""")
580+
addStatement(
581+
"println(%S)",
582+
"""
583+
584+
::warning title=Deprecated Binding Version Used::The used binding version $bindingVersion for ${coords.prettyPrint} is deprecated! First stable version is $firstStableVersion.
585+
""".trimIndent(),
586+
)
587+
endControlFlow()
588+
add("\n")
589+
}
590+
if (bindingVersion.isExperimental) {
591+
val lastStableVersion = BindingVersion.entries.findLast { !it.isDeprecated && !it.isExperimental }
592+
addStatement(
593+
"println(%S)",
594+
"""
595+
WARNING: The used binding version $bindingVersion for ${coords.prettyPrint} is experimental! Last stable version is $lastStableVersion.
596+
""".trimIndent(),
597+
)
598+
beginControlFlow("""if (System.getenv("GITHUB_ACTIONS").toBoolean())""")
599+
addStatement(
600+
"println(%S)",
601+
"""
602+
603+
::warning title=Experimental Binding Version Used::The used binding version $bindingVersion for ${coords.prettyPrint} is experimental! Last stable version is $lastStableVersion.
604+
""".trimIndent(),
605+
)
606+
endControlFlow()
607+
add("\n")
608+
}
609+
add(metadata.initializerBlock(inputTypings))
610+
},
611+
)
540612
return this
541613
}
542614

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.github.typesafegithub.workflows.actionbindinggenerator.versioning
2+
3+
public enum class BindingVersion(
4+
public val isDeprecated: Boolean = false,
5+
public val isExperimental: Boolean = true,
6+
public val libraryVersion: String,
7+
) {
8+
V1(isExperimental = false, libraryVersion = "3.0.0"),
9+
;
10+
11+
override fun toString(): String = super.toString().lowercase()
12+
}

0 commit comments

Comments
 (0)