Skip to content

Commit ed57b81

Browse files
committed
Support displaying typings from both sources
1 parent 00223f2 commit ed57b81

File tree

3 files changed

+119
-28
lines changed

3 files changed

+119
-28
lines changed
Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import androidx.compose.foundation.layout.Column
2+
import androidx.compose.foundation.layout.Row
23
import androidx.compose.foundation.layout.Spacer
34
import androidx.compose.foundation.layout.fillMaxWidth
45
import androidx.compose.foundation.layout.height
@@ -21,10 +22,13 @@ fun App() {
2122
MaterialTheme {
2223
var actionCoords by remember { mutableStateOf("actions/checkout@v4") }
2324
var manifest: Metadata? by remember { mutableStateOf(null) }
25+
var typingFromAction: Typing? by remember { mutableStateOf(null) }
26+
var typingFromCatalog: Typing? by remember { mutableStateOf(null) }
2427

2528
LaunchedEffect(actionCoords) {
26-
val actionManifestYaml = fetchManifest(actionCoords)
27-
manifest = actionManifestYaml
29+
manifest = fetchManifest(actionCoords)
30+
typingFromAction = fetchTypingFromAction(actionCoords)
31+
typingFromCatalog = fetchTypingFromCatalog(actionCoords)
2832
}
2933

3034
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
@@ -35,26 +39,59 @@ fun App() {
3539
)
3640
Spacer(Modifier.height(10.dp))
3741

38-
39-
Column(Modifier.verticalScroll(rememberScrollState())) {
40-
Text("Inputs", fontWeight = FontWeight.Bold)
41-
if (manifest?.inputs?.isEmpty() == true) {
42-
Text("<none>")
43-
}
44-
manifest?.inputs?.forEach {
45-
Text(it.key)
46-
}
47-
48-
Spacer(Modifier.height(10.dp))
49-
50-
Text("Outputs", fontWeight = FontWeight.Bold)
51-
if (manifest?.outputs?.isEmpty() == true) {
52-
Text("<none>")
53-
}
54-
manifest?.outputs?.forEach {
55-
Text(it.key)
56-
}
42+
Row {
43+
manifest(manifest)
44+
typing(typingFromAction, source = "action")
45+
typing(typingFromCatalog, source = "catalog")
5746
}
5847
}
5948
}
6049
}
50+
51+
@Composable
52+
private fun manifest(manifest: Metadata?) {
53+
Column(Modifier.verticalScroll(rememberScrollState())) {
54+
Text("Manifest:")
55+
Text("Inputs", fontWeight = FontWeight.Bold)
56+
if (manifest?.inputs?.isEmpty() == true) {
57+
Text("<none>")
58+
}
59+
manifest?.inputs?.forEach {
60+
Text(it.key)
61+
}
62+
63+
Spacer(Modifier.height(10.dp))
64+
65+
Text("Outputs", fontWeight = FontWeight.Bold)
66+
if (manifest?.outputs?.isEmpty() == true) {
67+
Text("<none>")
68+
}
69+
manifest?.outputs?.forEach {
70+
Text(it.key)
71+
}
72+
}
73+
}
74+
75+
@Composable
76+
private fun typing(typing: Typing?, source: String) {
77+
Column(Modifier.verticalScroll(rememberScrollState())) {
78+
Text("Typing from $source:")
79+
Text("Inputs", fontWeight = FontWeight.Bold)
80+
if (typing?.inputs?.isEmpty() == true) {
81+
Text("<none>")
82+
}
83+
typing?.inputs?.forEach {
84+
Text("${it.key}: ${it.value.type}")
85+
}
86+
87+
Spacer(Modifier.height(10.dp))
88+
89+
Text("Outputs", fontWeight = FontWeight.Bold)
90+
if (typing?.outputs?.isEmpty() == true) {
91+
Text("<none>")
92+
}
93+
typing?.outputs?.forEach {
94+
Text("${it.key}: ${it.value.type}")
95+
}
96+
}
97+
}

composeApp/src/commonMain/kotlin/ManifestFetching.kt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,35 @@ import io.ktor.client.request.get
44
import io.ktor.http.HttpStatusCode
55
import kotlinx.serialization.decodeFromString
66

7-
suspend fun fetchManifest(actionCoords: String): Metadata? {
8-
val yaml = listOf("yml", "yaml").firstNotNullOfOrNull { extension ->
7+
suspend fun fetchManifest(actionCoords: String): Metadata? =
8+
fetchYaml(urlWithoutExtension = "https://raw.githubusercontent.com/${actionCoords.replace("@", "/")}/action")
9+
?.let { decodeYamlFromString(it) }
10+
11+
suspend fun fetchTypingFromAction(actionCoords: String): Typing? =
12+
fetchYaml(urlWithoutExtension = "https://raw.githubusercontent.com/${actionCoords.replace("@", "/")}/action-types")
13+
?.let { decodeYamlFromString(it) }
14+
15+
suspend fun fetchTypingFromCatalog(actionCoords: String): Typing? =
16+
fetchYaml(urlWithoutExtension = "https://raw.githubusercontent.com/typesafegithub/github-actions-typing-catalog/main/typings/${actionCoords.replace("@", "/")}/action-types")
17+
?.let { decodeYamlFromString(it) }
18+
19+
suspend fun fetchYaml(urlWithoutExtension: String): String? =
20+
listOf("yml", "yaml").firstNotNullOfOrNull { extension ->
921
val response = client
10-
.get(urlString = "https://raw.githubusercontent.com/${actionCoords.replace("@", "/")}/action.$extension")
22+
.get(urlString = "${urlWithoutExtension}.$extension")
1123
if (response.status == HttpStatusCode.OK) {
1224
response.body<String>()
1325
} else {
1426
null
1527
}
16-
} ?: return null
28+
}
1729

18-
return try {
19-
myYaml.decodeFromString<Metadata>(yaml)
30+
private inline fun <reified T> decodeYamlFromString(yaml: String): T? =
31+
try {
32+
myYaml.decodeFromString<T>(yaml)
2033
} catch (e: Exception) {
2134
println("Exception: $e")
2235
null
2336
}
24-
}
2537

2638
private val myYaml = Yaml(configuration = Yaml.default.configuration.copy(strictMode = false))
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import kotlinx.serialization.SerialName
2+
import kotlinx.serialization.Serializable
3+
4+
@Serializable
5+
data class Typing(
6+
val inputs: Map<String, ActionType> = emptyMap(),
7+
val outputs: Map<String, ActionType> = emptyMap(),
8+
)
9+
10+
@Serializable
11+
data class ActionType(
12+
val type: ActionTypeEnum,
13+
val name: String? = null,
14+
@SerialName("named-values")
15+
val namedValues: Map<String, Int> = emptyMap(),
16+
val separator: String = "",
17+
@SerialName("allowed-values")
18+
val allowedValues: List<String> = emptyList(),
19+
@SerialName("list-item")
20+
val listItem: ActionType? = null,
21+
)
22+
23+
@Serializable
24+
enum class ActionTypeEnum {
25+
@SerialName("string")
26+
String,
27+
28+
@SerialName("boolean")
29+
Boolean,
30+
31+
@SerialName("integer")
32+
Integer,
33+
34+
@SerialName("float")
35+
Float,
36+
37+
@SerialName("list")
38+
List,
39+
40+
@SerialName("enum")
41+
Enum,
42+
}

0 commit comments

Comments
 (0)