Skip to content

Commit ef9782d

Browse files
committed
feat(abg): allow usage of version ranges by generating only major or minor version even with more detailed version
1 parent cd832fe commit ef9782d

File tree

16 files changed

+363
-64
lines changed

16 files changed

+363
-64
lines changed

action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,28 @@ public data class ActionCoords(
1111
* A top-level action is an action with its `action.y(a)ml` file in the repository root, as opposed to actions stored
1212
* in subdirectories.
1313
*/
14-
public val ActionCoords.isTopLevel: Boolean get() = "/" !in name
14+
public val ActionCoords.isTopLevel: Boolean get() = "__" !in name.substringBefore("___")
1515

16-
public val ActionCoords.prettyPrint: String get() = "$owner/$name@$version${typesUuid?.let { " (types: $it)" } ?: ""}"
16+
public val ActionCoords.prettyPrint: String
17+
get() = "$owner/${
18+
name.replace("___", " with ").replace("__", "/")
19+
}@$version${typesUuid?.let { " (types: $it)" } ?: ""}"
1720

1821
/**
1922
* For most actions, it's the same as [ActionCoords.name].
2023
* For actions that aren't executed from the root of the repo, it returns the repo name.
2124
*/
2225
public val ActionCoords.repoName: String get() =
23-
name.substringBefore("/")
26+
name.substringBefore("__")
2427

2528
/**
2629
* For most actions, it's empty.
2730
* For actions that aren't executed from the root of the repo, it returns the path relative to the repo root where the
2831
* action lives.
2932
*/
30-
public val ActionCoords.subName: String get() =
31-
if (isTopLevel) "" else "/${name.substringAfter("/")}"
33+
public val ActionCoords.subName: String
34+
get() =
35+
if (isTopLevel) "" else "/${name.substringAfter("__").substringBefore("___").replace("__", "/")}"
3236

3337
internal fun String.toActionCoords(): ActionCoords {
3438
val (ownerAndName, version) = this.split('@')

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.generation
33
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
44
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toPascalCase
55

6-
internal fun ActionCoords.buildActionClassName(): String = this.name.toPascalCase()
6+
internal fun ActionCoords.buildActionClassName(): String = this.name.substringBefore("___").toPascalCase()

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import com.squareup.kotlinpoet.asTypeName
1717
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
1818
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
1919
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource
20+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.isTopLevel
21+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.repoName
22+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
2023
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_INPUTS
2124
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_VERSION
2225
import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Input
@@ -415,10 +418,20 @@ private fun TypeSpec.Builder.inheritsFromRegularAction(
415418
return this
416419
.superclass(superclass)
417420
.addSuperclassConstructorParameter("%S", coords.owner)
418-
.addSuperclassConstructorParameter("%S", coords.name)
419-
.addSuperclassConstructorParameter("_customVersion ?: %S", coords.version)
421+
.addSuperclassConstructorParameter("%S", coords.name.substringBefore("___").replace("__", "/"))
422+
.addSuperclassConstructorParameter(
423+
"_customVersion ?: %S",
424+
when {
425+
coords.name.endsWith("___major") -> coords.version.majorVersion
426+
coords.name.endsWith("___minor") -> coords.version.minorVersion
427+
else -> coords.version
428+
},
429+
)
420430
}
421431

432+
private val String.majorVersion get() = substringBefore('.')
433+
private val String.minorVersion get() = split('.', limit = 3).take(2).joinToString(".")
434+
422435
private fun Metadata.primaryConstructor(
423436
inputTypings: Map<String, Typing>,
424437
coords: ActionCoords,
@@ -620,9 +633,7 @@ private fun actionKdoc(
620633
|
621634
|${metadata.description.escapedForComments.removeTrailingWhitespacesForEachLine()}
622635
|
623-
|[Action on GitHub](https://github.com/${coords.owner}/${coords.name.substringBefore(
624-
'/',
625-
)}${if ("/" in coords.name) "/tree/${coords.version}/${coords.name.substringAfter('/')}" else ""})
636+
|[Action on GitHub](https://github.com/${coords.owner}/${coords.repoName}${if (!coords.isTopLevel) "/tree/${coords.version}${coords.subName}" else ""})
626637
""".trimMargin()
627638

628639
private fun Map<String, Typing>?.getInputTyping(key: String) = this?.get(key) ?: StringTyping

action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReading.kt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCo
44
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.CommitHash
55
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
66
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.NewestForVersion
7+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.repoName
8+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
79
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.myYaml
810
import kotlinx.serialization.Serializable
911
import kotlinx.serialization.decodeFromString
@@ -35,17 +37,9 @@ public data class Output(
3537
val description: String = "",
3638
)
3739

38-
private fun ActionCoords.actionYmlUrl(gitRef: String) =
39-
"https://raw.githubusercontent.com/$owner/${name.substringBefore(
40-
'/',
41-
)}/$gitRef/${if ("/" in name) "${name.substringAfter('/')}/" else ""}action.yml"
40+
private fun ActionCoords.actionYmlUrl(gitRef: String) = "https://raw.githubusercontent.com/$owner/$repoName/$gitRef$subName/action.yml"
4241

43-
private fun ActionCoords.actionYamlUrl(gitRef: String) =
44-
"https://raw.githubusercontent.com/$owner/${name.substringBefore(
45-
'/',
46-
)}/$gitRef/${if ("/" in name) "${name.substringAfter('/')}/" else ""}action.yaml"
47-
48-
internal val ActionCoords.gitHubUrl: String get() = "https://github.com/$owner/$name"
42+
private fun ActionCoords.actionYamlUrl(gitRef: String) = "https://raw.githubusercontent.com/$owner/$repoName/$gitRef$subName/action.yaml"
4943

5044
public fun ActionCoords.fetchMetadata(
5145
metadataRevision: MetadataRevision,

action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/utils/TextUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal fun String.toPascalCase(): String {
77
val normalizedString = if (hasOnlyUppercases) lowercase() else this
88
return normalizedString
99
.replace("+", "-plus-")
10-
.split("-", "_", " ", ".", "/")
10+
.split("-", "_", " ", ".", "/", "__")
1111
.joinToString("") {
1212
it.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
1313
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// This file was generated using action-binding-generator. Don't change it by hand, otherwise your
2+
// changes will be overwritten with the next binding code regeneration.
3+
// See https://github.com/typesafegithub/github-workflows-kt for more info.
4+
@file:Suppress(
5+
"DataClassPrivateConstructor",
6+
"UNUSED_PARAMETER",
7+
)
8+
9+
package io.github.typesafegithub.workflows.actions.johnsmith
10+
11+
import io.github.typesafegithub.workflows.domain.actions.Action
12+
import io.github.typesafegithub.workflows.domain.actions.RegularAction
13+
import java.util.LinkedHashMap
14+
import kotlin.String
15+
import kotlin.Suppress
16+
import kotlin.Unit
17+
import kotlin.collections.Map
18+
19+
/**
20+
* Action: Action With No Inputs
21+
*
22+
* Description
23+
*
24+
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-major-version)
25+
*
26+
* @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by
27+
* the binding
28+
* @param _customVersion Allows overriding action's version, for example to use a specific minor
29+
* version, or a newer version that the binding doesn't yet know about
30+
*/
31+
public data class ActionWithNoInputsWithMajorVersion private constructor(
32+
/**
33+
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
34+
*/
35+
public val _customInputs: Map<String, String> = mapOf(),
36+
/**
37+
* Allows overriding action's version, for example to use a specific minor version, or a newer
38+
* version that the binding doesn't yet know about
39+
*/
40+
public val _customVersion: String? = null,
41+
) : RegularAction<Action.Outputs>("john-smith", "action-with-no-inputs-with-major-version",
42+
_customVersion ?: "v3") {
43+
public constructor(
44+
vararg pleaseUseNamedArguments: Unit,
45+
_customInputs: Map<String, String> = mapOf(),
46+
_customVersion: String? = null,
47+
) : this(_customInputs = _customInputs, _customVersion = _customVersion)
48+
49+
@Suppress("SpreadOperator")
50+
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)
51+
52+
override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// This file was generated using action-binding-generator. Don't change it by hand, otherwise your
2+
// changes will be overwritten with the next binding code regeneration.
3+
// See https://github.com/typesafegithub/github-workflows-kt for more info.
4+
@file:Suppress(
5+
"DataClassPrivateConstructor",
6+
"UNUSED_PARAMETER",
7+
)
8+
9+
package io.github.typesafegithub.workflows.actions.johnsmith
10+
11+
import io.github.typesafegithub.workflows.domain.actions.Action
12+
import io.github.typesafegithub.workflows.domain.actions.RegularAction
13+
import java.util.LinkedHashMap
14+
import kotlin.Deprecated
15+
import kotlin.String
16+
import kotlin.Suppress
17+
import kotlin.Unit
18+
import kotlin.collections.Map
19+
20+
/**
21+
* ```text
22+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23+
* !!! WARNING !!!
24+
* !!! !!!
25+
* !!! This action binding has no typings provided. All inputs will !!!
26+
* !!! have a default type of String. !!!
27+
* !!! To be able to use this action in a type-safe way, ask the !!!
28+
* !!! action's owner to provide the typings using !!!
29+
* !!! !!!
30+
* !!! https://github.com/typesafegithub/github-actions-typing !!!
31+
* !!! !!!
32+
* !!! or if it's impossible, contribute typings to a community-driven !!!
33+
* !!! !!!
34+
* !!! https://github.com/typesafegithub/github-actions-typing-catalog !!!
35+
* !!! !!!
36+
* !!! This '_Untyped' binding will be available even once the typings !!!
37+
* !!! are added. !!!
38+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39+
* ```
40+
*
41+
* Action: Action With No Inputs
42+
*
43+
* Description
44+
*
45+
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-major-version)
46+
*
47+
* @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by
48+
* the binding
49+
* @param _customVersion Allows overriding action's version, for example to use a specific minor
50+
* version, or a newer version that the binding doesn't yet know about
51+
*/
52+
@Deprecated(
53+
"Use the typed class instead",
54+
ReplaceWith("ActionWithNoInputsWithMajorVersion"),
55+
)
56+
public data class ActionWithNoInputsWithMajorVersion_Untyped private constructor(
57+
/**
58+
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
59+
*/
60+
public val _customInputs: Map<String, String> = mapOf(),
61+
/**
62+
* Allows overriding action's version, for example to use a specific minor version, or a newer
63+
* version that the binding doesn't yet know about
64+
*/
65+
public val _customVersion: String? = null,
66+
) : RegularAction<Action.Outputs>("john-smith", "action-with-no-inputs-with-major-version",
67+
_customVersion ?: "v3") {
68+
public constructor(
69+
vararg pleaseUseNamedArguments: Unit,
70+
_customInputs: Map<String, String> = mapOf(),
71+
_customVersion: String? = null,
72+
) : this(_customInputs = _customInputs, _customVersion = _customVersion)
73+
74+
@Suppress("SpreadOperator")
75+
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)
76+
77+
override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// This file was generated using action-binding-generator. Don't change it by hand, otherwise your
2+
// changes will be overwritten with the next binding code regeneration.
3+
// See https://github.com/typesafegithub/github-workflows-kt for more info.
4+
@file:Suppress(
5+
"DataClassPrivateConstructor",
6+
"UNUSED_PARAMETER",
7+
)
8+
9+
package io.github.typesafegithub.workflows.actions.johnsmith
10+
11+
import io.github.typesafegithub.workflows.domain.actions.Action
12+
import io.github.typesafegithub.workflows.domain.actions.RegularAction
13+
import java.util.LinkedHashMap
14+
import kotlin.String
15+
import kotlin.Suppress
16+
import kotlin.Unit
17+
import kotlin.collections.Map
18+
19+
/**
20+
* Action: Action With No Inputs
21+
*
22+
* Description
23+
*
24+
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-minor-version)
25+
*
26+
* @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by
27+
* the binding
28+
* @param _customVersion Allows overriding action's version, for example to use a specific minor
29+
* version, or a newer version that the binding doesn't yet know about
30+
*/
31+
public data class ActionWithNoInputsWithMinorVersion private constructor(
32+
/**
33+
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
34+
*/
35+
public val _customInputs: Map<String, String> = mapOf(),
36+
/**
37+
* Allows overriding action's version, for example to use a specific minor version, or a newer
38+
* version that the binding doesn't yet know about
39+
*/
40+
public val _customVersion: String? = null,
41+
) : RegularAction<Action.Outputs>("john-smith", "action-with-no-inputs-with-minor-version",
42+
_customVersion ?: "v3.1") {
43+
public constructor(
44+
vararg pleaseUseNamedArguments: Unit,
45+
_customInputs: Map<String, String> = mapOf(),
46+
_customVersion: String? = null,
47+
) : this(_customInputs = _customInputs, _customVersion = _customVersion)
48+
49+
@Suppress("SpreadOperator")
50+
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)
51+
52+
override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// This file was generated using action-binding-generator. Don't change it by hand, otherwise your
2+
// changes will be overwritten with the next binding code regeneration.
3+
// See https://github.com/typesafegithub/github-workflows-kt for more info.
4+
@file:Suppress(
5+
"DataClassPrivateConstructor",
6+
"UNUSED_PARAMETER",
7+
)
8+
9+
package io.github.typesafegithub.workflows.actions.johnsmith
10+
11+
import io.github.typesafegithub.workflows.domain.actions.Action
12+
import io.github.typesafegithub.workflows.domain.actions.RegularAction
13+
import java.util.LinkedHashMap
14+
import kotlin.Deprecated
15+
import kotlin.String
16+
import kotlin.Suppress
17+
import kotlin.Unit
18+
import kotlin.collections.Map
19+
20+
/**
21+
* ```text
22+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23+
* !!! WARNING !!!
24+
* !!! !!!
25+
* !!! This action binding has no typings provided. All inputs will !!!
26+
* !!! have a default type of String. !!!
27+
* !!! To be able to use this action in a type-safe way, ask the !!!
28+
* !!! action's owner to provide the typings using !!!
29+
* !!! !!!
30+
* !!! https://github.com/typesafegithub/github-actions-typing !!!
31+
* !!! !!!
32+
* !!! or if it's impossible, contribute typings to a community-driven !!!
33+
* !!! !!!
34+
* !!! https://github.com/typesafegithub/github-actions-typing-catalog !!!
35+
* !!! !!!
36+
* !!! This '_Untyped' binding will be available even once the typings !!!
37+
* !!! are added. !!!
38+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39+
* ```
40+
*
41+
* Action: Action With No Inputs
42+
*
43+
* Description
44+
*
45+
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-minor-version)
46+
*
47+
* @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by
48+
* the binding
49+
* @param _customVersion Allows overriding action's version, for example to use a specific minor
50+
* version, or a newer version that the binding doesn't yet know about
51+
*/
52+
@Deprecated(
53+
"Use the typed class instead",
54+
ReplaceWith("ActionWithNoInputsWithMinorVersion"),
55+
)
56+
public data class ActionWithNoInputsWithMinorVersion_Untyped private constructor(
57+
/**
58+
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
59+
*/
60+
public val _customInputs: Map<String, String> = mapOf(),
61+
/**
62+
* Allows overriding action's version, for example to use a specific minor version, or a newer
63+
* version that the binding doesn't yet know about
64+
*/
65+
public val _customVersion: String? = null,
66+
) : RegularAction<Action.Outputs>("john-smith", "action-with-no-inputs-with-minor-version",
67+
_customVersion ?: "v3.1") {
68+
public constructor(
69+
vararg pleaseUseNamedArguments: Unit,
70+
_customInputs: Map<String, String> = mapOf(),
71+
_customVersion: String? = null,
72+
) : this(_customInputs = _customInputs, _customVersion = _customVersion)
73+
74+
@Suppress("SpreadOperator")
75+
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)
76+
77+
override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
78+
}

action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/generation/ClassNamingTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ class ClassNamingTest :
99
context("buildActionClassName") {
1010
listOf(
1111
ActionCoords("irrelevant", "some-action-name", "v2") to "SomeActionName",
12-
ActionCoords("irrelevant", "some-action-name/subaction", "v2") to "SomeActionNameSubaction",
13-
ActionCoords("irrelevant", "some-action-name/foo/bar/baz", "v2") to "SomeActionNameFooBarBaz",
12+
ActionCoords("irrelevant", "some-action-name__subaction", "v2") to "SomeActionNameSubaction",
13+
ActionCoords("irrelevant", "some-action-name__foo__bar__baz", "v2") to "SomeActionNameFooBarBaz",
14+
ActionCoords("irrelevant", "some-action-name__foo__bar__baz___major", "v2") to "SomeActionNameFooBarBaz",
1415
).forEach { (input, output) ->
1516
test("should get '$input' and produce '$output'") {
1617
input.buildActionClassName() shouldBe output

0 commit comments

Comments
 (0)