Skip to content

Commit 0343909

Browse files
authored
refactor: unify content of ActionCoords name (#1646)
Before these changes, `ActionCoords#name` sometimes had the actual action coordinates, so for example `some-name__some-sub`, sometimes it had the replaced `some-name/some-sub`. This is not good, as you never know what you get and also led to certain bugs where wrong things are written to metadata files for example. This changes unifies the situation, so that the `name` only contains the repository name and the `path` is in a separate property with slashes. All other manipulation is then done where needed.
1 parent a5b842c commit 0343909

File tree

18 files changed

+188
-127
lines changed

18 files changed

+188
-127
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
public final class io/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords {
2-
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
2+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
3+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
34
public final fun component1 ()Ljava/lang/String;
45
public final fun component2 ()Ljava/lang/String;
56
public final fun component3 ()Ljava/lang/String;
6-
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;
7-
public static synthetic fun copy$default (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;
7+
public final fun component4 ()Ljava/lang/String;
8+
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;
9+
public static synthetic fun copy$default (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;
810
public fun equals (Ljava/lang/Object;)Z
911
public final fun getName ()Ljava/lang/String;
1012
public final fun getOwner ()Ljava/lang/String;
13+
public final fun getPath ()Ljava/lang/String;
1114
public final fun getVersion ()Ljava/lang/String;
1215
public fun hashCode ()I
1316
public fun toString ()Ljava/lang/String;
1417
}
1518

1619
public final class io/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoordsKt {
20+
public static final fun getFullName (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;)Ljava/lang/String;
1721
public static final fun getPrettyPrint (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;)Ljava/lang/String;
18-
public static final fun getRepoName (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;)Ljava/lang/String;
1922
public static final fun getSubName (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;)Ljava/lang/String;
2023
public static final fun isTopLevel (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;)Z
2124
}

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,39 @@ public data class ActionCoords(
44
val owner: String,
55
val name: String,
66
val version: String,
7+
val path: String? = null,
78
)
89

910
/**
1011
* A top-level action is an action with its `action.y(a)ml` file in the repository root, as opposed to actions stored
1112
* in subdirectories.
1213
*/
13-
public val ActionCoords.isTopLevel: Boolean get() = "/" !in name
14+
public val ActionCoords.isTopLevel: Boolean get() = path == null
1415

15-
public val ActionCoords.prettyPrint: String get() = "$owner/$name@$version"
16+
public val ActionCoords.prettyPrint: String get() = "$owner/$fullName@$version"
1617

1718
/**
18-
* For most actions, it's the same as [ActionCoords.name].
19-
* For actions that aren't executed from the root of the repo, it returns the repo name.
19+
* For most actions, it's empty.
20+
* For actions that aren't executed from the root of the repo, it returns the path relative to the repo root where the
21+
* action lives, starting with a slash.
2022
*/
21-
public val ActionCoords.repoName: String get() =
22-
name.substringBefore("/")
23+
public val ActionCoords.subName: String get() = path?.let { "/$path" } ?: ""
2324

2425
/**
25-
* For most actions, it's empty.
26-
* For actions that aren't executed from the root of the repo, it returns the path relative to the repo root where the
26+
* For most actions, it's equal to [ActionCoords.name].
27+
* For actions that aren't executed from the root of the repo, it returns the path starting with the repo root where the
2728
* action lives.
2829
*/
29-
public val ActionCoords.subName: String get() =
30-
if (isTopLevel) "" else "/${name.substringAfter("/")}"
30+
public val ActionCoords.fullName: String get() = "$name$subName"
3131

3232
internal fun String.toActionCoords(): ActionCoords {
33-
val (ownerAndName, version) = this.split('@')
34-
val (owner, name) = ownerAndName.split('/', limit = 2)
33+
val (coordinates, version) = this.split('@')
34+
val coordinateParts = coordinates.split('/')
35+
val (owner, name) = coordinateParts
3536
return ActionCoords(
3637
owner = owner,
3738
name = name,
3839
version = version,
40+
path = coordinateParts.drop(2).joinToString("/").takeUnless { it.isBlank() },
3941
)
4042
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.typesafegithub.workflows.actionbindinggenerator.generation
22

33
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
4+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.fullName
45
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toPascalCase
56

6-
internal fun ActionCoords.buildActionClassName(): String = this.name.toPascalCase()
7+
internal fun ActionCoords.buildActionClassName(): String = this.fullName.toPascalCase()

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ 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.fullName
22+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.isTopLevel
23+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
2124
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_INPUTS
2225
import io.github.typesafegithub.workflows.actionbindinggenerator.generation.Properties.CUSTOM_VERSION
2326
import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Input
@@ -411,7 +414,7 @@ private fun TypeSpec.Builder.inheritsFromRegularAction(
411414
return this
412415
.superclass(superclass)
413416
.addSuperclassConstructorParameter("%S", coords.owner)
414-
.addSuperclassConstructorParameter("%S", coords.name)
417+
.addSuperclassConstructorParameter("%S", coords.fullName)
415418
.addSuperclassConstructorParameter("_customVersion ?: %S", coords.version)
416419
}
417420

@@ -614,9 +617,7 @@ private fun actionKdoc(
614617
|
615618
|${metadata.description.escapedForComments.removeTrailingWhitespacesForEachLine()}
616619
|
617-
|[Action on GitHub](https://github.com/${coords.owner}/${coords.name.substringBefore(
618-
'/',
619-
)}${if ("/" in coords.name) "/tree/${coords.version}/${coords.name.substringAfter('/')}" else ""})
620+
|[Action on GitHub](https://github.com/${coords.owner}/${coords.name}${if (coords.isTopLevel) "" else "/tree/${coords.version}${coords.subName}"})
620621
""".trimMargin()
621622

622623
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: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCo
55
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.CommitHash
66
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
77
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.NewestForVersion
8+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
89
import kotlinx.serialization.Serializable
910
import kotlinx.serialization.decodeFromString
1011
import java.io.IOException
@@ -35,15 +36,9 @@ public data class Output(
3536
val description: String = "",
3637
)
3738

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"
39+
private fun ActionCoords.actionYmlUrl(gitRef: String) = "https://raw.githubusercontent.com/$owner/$name/$gitRef$subName/action.yml"
4240

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"
41+
private fun ActionCoords.actionYamlUrl(gitRef: String) = "https://raw.githubusercontent.com/$owner/$name/$gitRef$subName/action.yaml"
4742

4843
internal val ActionCoords.gitHubUrl: String get() = "https://github.com/$owner/$name"
4944

action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/typing/TypesProviding.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import io.github.typesafegithub.workflows.actionbindinggenerator.domain.NewestFo
88
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource
99
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource.ACTION
1010
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.TypingActualSource.TYPING_CATALOG
11-
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.repoName
1211
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.subName
1312
import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.fetchUri
1413
import io.github.typesafegithub.workflows.actionbindinggenerator.utils.toPascalCase
@@ -29,18 +28,18 @@ internal fun ActionCoords.provideTypes(
2928
?: Pair(emptyMap(), null)
3029

3130
private fun ActionCoords.actionTypesYmlUrl(gitRef: String) =
32-
"https://raw.githubusercontent.com/$owner/$repoName/$gitRef$subName/action-types.yml"
31+
"https://raw.githubusercontent.com/$owner/$name/$gitRef$subName/action-types.yml"
3332

3433
private fun ActionCoords.actionTypesFromCatalog() =
3534
"https://raw.githubusercontent.com/typesafegithub/github-actions-typing-catalog/" +
36-
"main/typings/$owner/$repoName/$version$subName/action-types.yml"
35+
"main/typings/$owner/$name/$version$subName/action-types.yml"
3736

3837
private fun ActionCoords.catalogMetadata() =
3938
"https://raw.githubusercontent.com/typesafegithub/github-actions-typing-catalog/" +
40-
"main/typings/$owner/$repoName/metadata.yml"
39+
"main/typings/$owner/$name/metadata.yml"
4140

4241
private fun ActionCoords.actionTypesYamlUrl(gitRef: String) =
43-
"https://raw.githubusercontent.com/$owner/$repoName/$gitRef$subName/action-types.yaml"
42+
"https://raw.githubusercontent.com/$owner/$name/$gitRef$subName/action-types.yaml"
4443

4544
private fun ActionCoords.fetchTypingMetadata(
4645
metadataRevision: MetadataRevision,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.ExposedCopyVisibility
15+
import kotlin.String
16+
import kotlin.Suppress
17+
import kotlin.Unit
18+
import kotlin.collections.Map
19+
20+
/**
21+
* Action: Action With No Inputs
22+
*
23+
* Description
24+
*
25+
* [Action on GitHub](https://github.com/john-smith/action-with/tree/v3/sub/action)
26+
*
27+
* @param _customInputs Type-unsafe map where you can put any inputs that are not yet supported by the binding
28+
* @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
29+
*/
30+
@ExposedCopyVisibility
31+
public data class ActionWithSubAction 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 version that the binding doesn't yet know about
38+
*/
39+
public val _customVersion: String? = null,
40+
) : RegularAction<Action.Outputs>("john-smith", "action-with/sub/action", _customVersion ?: "v3") {
41+
public constructor(
42+
vararg pleaseUseNamedArguments: Unit,
43+
_customInputs: Map<String, String> = mapOf(),
44+
_customVersion: String? = null,
45+
) : this(_customInputs = _customInputs, _customVersion = _customVersion)
46+
47+
@Suppress("SpreadOperator")
48+
override fun toYamlArguments(): LinkedHashMap<String, String> = LinkedHashMap(_customInputs)
49+
50+
override fun buildOutputObject(stepId: String): Action.Outputs = Outputs(stepId)
51+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ 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", "v2", "subaction") to "SomeActionNameSubaction",
13+
ActionCoords("irrelevant", "some-action-name", "v2", "foo/bar/baz") to "SomeActionNameFooBarBaz",
1414
).forEach { (input, output) ->
1515
test("should get '$input' and produce '$output'") {
1616
input.buildActionClassName() shouldBe output

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,30 @@ class GenerationTest :
287287
binding.shouldContainAndMatchFile("ActionWithNoInputs.kt")
288288
}
289289

290+
test("subaction") {
291+
// given
292+
val actionManifestHasNoInputs = emptyMap<String, Input>()
293+
val actionManifest =
294+
Metadata(
295+
inputs = actionManifestHasNoInputs,
296+
name = "Action With No Inputs",
297+
description = "Description",
298+
)
299+
300+
val coords = ActionCoords("john-smith", "action-with", "v3", "sub/action")
301+
302+
// when
303+
val binding =
304+
coords.generateBinding(
305+
metadataRevision = NewestForVersion,
306+
metadata = actionManifest,
307+
inputTypings = Pair(emptyMap(), ACTION),
308+
)
309+
310+
// then
311+
binding.shouldContainAndMatchFile("ActionWithSubAction.kt")
312+
}
313+
290314
test("action with deprecated input resolving to the same Kotlin field name") {
291315
// given
292316
val actionManifest =

action-binding-generator/src/test/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/typing/TypesProvidingTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class TypesProvidingTest :
129129
else -> throw IOException()
130130
}
131131
}
132-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v3")
132+
val actionCoord = ActionCoords("some-owner", "some-name", "v3", "some-sub")
133133

134134
// When
135135
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)
@@ -166,7 +166,7 @@ class TypesProvidingTest :
166166
else -> throw IOException()
167167
}
168168
}
169-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v3")
169+
val actionCoord = ActionCoords("some-owner", "some-name", "v3", "some-sub")
170170

171171
// When
172172
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)
@@ -208,7 +208,7 @@ class TypesProvidingTest :
208208
else -> throw IOException()
209209
}
210210
}
211-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v3")
211+
val actionCoord = ActionCoords("some-owner", "some-name", "v3", "some-sub")
212212

213213
// When
214214
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)
@@ -250,7 +250,7 @@ class TypesProvidingTest :
250250
else -> throw IOException()
251251
}
252252
}
253-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v3")
253+
val actionCoord = ActionCoords("some-owner", "some-name", "v3", "some-sub")
254254

255255
// When
256256
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)
@@ -302,7 +302,7 @@ class TypesProvidingTest :
302302
else -> throw IOException()
303303
}
304304
}
305-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v3")
305+
val actionCoord = ActionCoords("some-owner", "some-name", "v3", "some-sub")
306306

307307
// When
308308
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)
@@ -354,7 +354,7 @@ class TypesProvidingTest :
354354
else -> throw IOException()
355355
}
356356
}
357-
val actionCoord = ActionCoords("some-owner", "some-name/some-sub", "v6")
357+
val actionCoord = ActionCoords("some-owner", "some-name", "v6", "some-sub")
358358

359359
// When
360360
val types = actionCoord.provideTypes(metadataRevision = CommitHash("some-hash"), fetchUri = fetchUri)

0 commit comments

Comments
 (0)