Skip to content

Commit

Permalink
feat(abg): allow usage of version ranges by generating only major or …
Browse files Browse the repository at this point in the history
…minor version even with more detailed version
  • Loading branch information
Vampire committed Aug 20, 2024
1 parent af0de7b commit cb4a8a3
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,28 @@ public data class ActionCoords(
* A top-level action is an action with its `action.y(a)ml` file in the repository root, as opposed to actions stored
* in subdirectories.
*/
public val ActionCoords.isTopLevel: Boolean get() = "/" !in name
public val ActionCoords.isTopLevel: Boolean get() = "__" !in name.substringBefore("___")

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

/**
* For most actions, it's the same as [ActionCoords.name].
* For actions that aren't executed from the root of the repo, it returns the repo name.
*/
public val ActionCoords.repoName: String get() =
name.substringBefore("/")
name.substringBefore("__")

/**
* For most actions, it's empty.
* For actions that aren't executed from the root of the repo, it returns the path relative to the repo root where the
* action lives.
*/
public val ActionCoords.subName: String get() =
if (isTopLevel) "" else "/${name.substringAfter("/")}"
public val ActionCoords.subName: String
get() =
if (isTopLevel) "" else "/${name.substringAfter("__").substringBefore("___").replace("__", "/")}"

internal fun String.toActionCoords(): ActionCoords {
val (ownerAndName, version) = this.split('@')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package io.github.typesafegithub.workflows.actionbindinggenerator.generation
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toPascalCase

internal fun ActionCoords.buildActionClassName(): String = this.name.toPascalCase()
internal fun ActionCoords.buildActionClassName(): String = this.name.substringBefore("___").toPascalCase()
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import com.squareup.kotlinpoet.asTypeName
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.isTopLevel
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.repoName
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
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.metadata.Input
Expand Down Expand Up @@ -396,10 +399,20 @@ private fun TypeSpec.Builder.inheritsFromRegularAction(
return this
.superclass(superclass)
.addSuperclassConstructorParameter("%S", coords.owner)
.addSuperclassConstructorParameter("%S", coords.name)
.addSuperclassConstructorParameter("_customVersion ?: %S", coords.version)
.addSuperclassConstructorParameter("%S", coords.name.substringBefore("___").replace("__", "/"))
.addSuperclassConstructorParameter(
"_customVersion ?: %S",
when {
coords.name.endsWith("___major") -> coords.version.majorVersion
coords.name.endsWith("___minor") -> coords.version.minorVersion
else -> coords.version
},
)
}

private val String.majorVersion get() = substringBefore('.')
private val String.minorVersion get() = split('.', limit = 3).take(2).joinToString(".")

private fun Metadata.primaryConstructor(
inputTypings: Map<String, Typing>,
coords: ActionCoords,
Expand Down Expand Up @@ -590,9 +603,7 @@ private fun actionKdoc(
|
|${metadata.description.escapedForComments.removeTrailingWhitespacesForEachLine()}
|
|[Action on GitHub](https://github.com/${coords.owner}/${coords.name.substringBefore(
'/',
)}${if ("/" in coords.name) "/tree/${coords.version}/${coords.name.substringAfter('/')}" else ""})
|[Action on GitHub](https://github.com/${coords.owner}/${coords.repoName}${if (!coords.isTopLevel) "/tree/${coords.version}${coords.subName}" else ""})
""".trimMargin()

private fun Map<String, Typing>?.getInputTyping(key: String) = this?.get(key) ?: StringTyping
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCo
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.CommitHash
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.NewestForVersion
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.repoName
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.myYaml
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
Expand Down Expand Up @@ -35,17 +37,9 @@ public data class Output(
val description: String = "",
)

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

private fun ActionCoords.actionYamlUrl(gitRef: String) =
"https://raw.githubusercontent.com/$owner/${name.substringBefore(
'/',
)}/$gitRef/${if ("/" in name) "${name.substringAfter('/')}/" else ""}action.yaml"

internal val ActionCoords.gitHubUrl: String get() = "https://github.com/$owner/$name"
private fun ActionCoords.actionYamlUrl(gitRef: String) = "https://raw.githubusercontent.com/$owner/$repoName/$gitRef$subName/action.yaml"

public fun ActionCoords.fetchMetadata(
metadataRevision: MetadataRevision,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal fun String.toPascalCase(): String {
val normalizedString = if (hasOnlyUppercases) lowercase() else this
return normalizedString
.replace("+", "-plus-")
.split("-", "_", " ", ".", "/")
.split("-", "_", " ", ".", "/", "__")
.joinToString("") {
it.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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(
"DataClassPrivateConstructor",
"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 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-with-major-version)
*
* @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 data class ActionWithNoInputsWithMajorVersion private constructor(
/**
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
*/
public val _customInputs: Map<String, String> = 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<Action.Outputs>("john-smith", "action-with-no-inputs-with-major-version",
_customVersion ?: "v3") {
public constructor(
vararg pleaseUseNamedArguments: Unit,
_customInputs: Map<String, String> = mapOf(),
_customVersion: String? = null,
) : this(_customInputs = _customInputs, _customVersion = _customVersion)

@Suppress("SpreadOperator")
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)

override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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(
"DataClassPrivateConstructor",
"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 kotlin.Deprecated
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.Map

/**
* ```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: Action With No Inputs
*
* Description
*
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-major-version)
*
* @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("ActionWithNoInputsWithMajorVersion"),
)
public data class ActionWithNoInputsWithMajorVersion_Untyped private constructor(
/**
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
*/
public val _customInputs: Map<String, String> = 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<Action.Outputs>("john-smith", "action-with-no-inputs-with-major-version",
_customVersion ?: "v3") {
public constructor(
vararg pleaseUseNamedArguments: Unit,
_customInputs: Map<String, String> = mapOf(),
_customVersion: String? = null,
) : this(_customInputs = _customInputs, _customVersion = _customVersion)

@Suppress("SpreadOperator")
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)

override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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(
"DataClassPrivateConstructor",
"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 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-with-minor-version)
*
* @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 data class ActionWithNoInputsWithMinorVersion private constructor(
/**
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
*/
public val _customInputs: Map<String, String> = 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<Action.Outputs>("john-smith", "action-with-no-inputs-with-minor-version",
_customVersion ?: "v3.1") {
public constructor(
vararg pleaseUseNamedArguments: Unit,
_customInputs: Map<String, String> = mapOf(),
_customVersion: String? = null,
) : this(_customInputs = _customInputs, _customVersion = _customVersion)

@Suppress("SpreadOperator")
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)

override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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(
"DataClassPrivateConstructor",
"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 kotlin.Deprecated
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.Map

/**
* ```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: Action With No Inputs
*
* Description
*
* [Action on GitHub](https://github.com/john-smith/action-with-no-inputs-with-minor-version)
*
* @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("ActionWithNoInputsWithMinorVersion"),
)
public data class ActionWithNoInputsWithMinorVersion_Untyped private constructor(
/**
* Type-unsafe map where you can put any inputs that are not yet supported by the binding
*/
public val _customInputs: Map<String, String> = 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<Action.Outputs>("john-smith", "action-with-no-inputs-with-minor-version",
_customVersion ?: "v3.1") {
public constructor(
vararg pleaseUseNamedArguments: Unit,
_customInputs: Map<String, String> = mapOf(),
_customVersion: String? = null,
) : this(_customInputs = _customInputs, _customVersion = _customVersion)

@Suppress("SpreadOperator")
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)

override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ class ClassNamingTest :
context("buildActionClassName") {
listOf(
ActionCoords("irrelevant", "some-action-name", "v2") to "SomeActionName",
ActionCoords("irrelevant", "some-action-name/subaction", "v2") to "SomeActionNameSubaction",
ActionCoords("irrelevant", "some-action-name/foo/bar/baz", "v2") to "SomeActionNameFooBarBaz",
ActionCoords("irrelevant", "some-action-name__subaction", "v2") to "SomeActionNameSubaction",
ActionCoords("irrelevant", "some-action-name__foo__bar__baz", "v2") to "SomeActionNameFooBarBaz",
ActionCoords("irrelevant", "some-action-name__foo__bar__baz___major", "v2") to "SomeActionNameFooBarBaz",
).forEach { (input, output) ->
test("should get '$input' and produce '$output'") {
input.buildActionClassName() shouldBe output
Expand Down
Loading

0 comments on commit cb4a8a3

Please sign in to comment.