Repository: typesafegithub/github-workflows-kt
Pull request #1256 (2024-02-04 22:46:55)

feat(automation): print diffs in inputs/outputs when suggesting versions


Patch:
diff --git a/action-binding-generator/api/action-binding-generator.api b/action-binding-generator/api/action-binding-generator.api
index 4f4586da0..ad7599db0 100644
--- a/action-binding-generator/api/action-binding-generator.api
+++ b/action-binding-generator/api/action-binding-generator.api
@@ -163,6 +163,11 @@ public final class io/github/typesafegithub/workflows/actionbindinggenerator/met
 	public final fun serializer ()Lkotlinx/serialization/KSerializer;
 }
 
+public final class io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReadingKt {
+	public static final fun fetchMetadata (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lkotlin/jvm/functions/Function1;)Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;
+	public static synthetic fun fetchMetadata$default (Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/ActionCoords;Lio/github/typesafegithub/workflows/actionbindinggenerator/domain/MetadataRevision;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Metadata;
+}
+
 public final class io/github/typesafegithub/workflows/actionbindinggenerator/metadata/Output {
 	public static final field Companion Lio/github/typesafegithub/workflows/actionbindinggenerator/metadata/Output$Companion;
 	public fun <init> ()V
diff --git a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReading.kt b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReading.kt
index 42a2e24b7..80c502359 100644
--- a/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReading.kt
+++ b/action-binding-generator/src/main/kotlin/io/github/typesafegithub/workflows/actionbindinggenerator/metadata/MetadataReading.kt
@@ -52,7 +52,7 @@ internal val ActionCoords.releasesUrl: String get() = "$gitHubUrl/releases"
 
 internal val ActionCoords.gitHubUrl: String get() = "https://github.com/$owner/$name"
 
-internal fun ActionCoords.fetchMetadata(
+public fun ActionCoords.fetchMetadata(
     metadataRevision: MetadataRevision,
     fetchUri: (URI) -> String = ::fetchUri,
 ): Metadata {
diff --git a/automation/code-generator/src/main/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersions.kt b/automation/code-generator/src/main/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersions.kt
index 9e924fd3b..478d42eb3 100644
--- a/automation/code-generator/src/main/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersions.kt
+++ b/automation/code-generator/src/main/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersions.kt
@@ -1,8 +1,13 @@
 package io.github.typesafegithub.workflows.codegenerator.versions
 
 import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
+import io.github.typesafegithub.workflows.actionbindinggenerator.domain.FromLockfile
+import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
+import io.github.typesafegithub.workflows.actionbindinggenerator.domain.NewestForVersion
 import io.github.typesafegithub.workflows.actionbindinggenerator.domain.isTopLevel
 import io.github.typesafegithub.workflows.actionbindinggenerator.domain.prettyPrint
+import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Metadata
+import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.fetchMetadata
 import io.github.typesafegithub.workflows.codegenerator.bindingsToGenerate
 import io.github.typesafegithub.workflows.codegenerator.model.Version
 import java.io.File
@@ -63,6 +68,7 @@ fun List<GithubRef>.versions(): List<Version> =
 fun ActionCoords.suggestNewerVersion(
     existingVersions: List<Version>,
     availableVersions: List<Version>,
+    fetchMeta: ActionCoords.(MetadataRevision) -> Metadata = { this.fetchMetadata(it) },
 ): String? {
     if (availableVersions.isEmpty()) {
         return null
@@ -77,13 +83,18 @@ fun ActionCoords.suggestNewerVersion(
             .filter { it.isMajorVersion() }
             .sorted()
 
+    val metadata by lazy { this.copy(version = maxExisting.version).fetchMeta(FromLockfile) }
+
     val newerMajorVersions =
         majorVersions.filter { it > maxExisting }.sorted()
-            .map { "$it ([diff](${this.buildGitHubComparisonUrl(maxExisting, it)}))" }
+            .map {
+                val thisMetadata = this@suggestNewerVersion.copy(version = it.version).fetchMeta(NewestForVersion)
+                val addedInputs = thisMetadata.inputs.keys - metadata.inputs.keys
+                val removedInputs = metadata.inputs.keys - thisMetadata.inputs.keys
+                val addedOutputs = thisMetadata.outputs.keys - metadata.outputs.keys
+                val removedOutputs = metadata.outputs.keys - thisMetadata.outputs.keys
+                "$it (added inputs: $addedInputs, removed inputs: $removedInputs, " +
+                    "added outputs: $addedOutputs, removed outputs: $removedOutputs)"
+            }
     return "new version(s) available: $newerMajorVersions".takeIf { newerMajorVersions.isNotEmpty() }
 }
-
-private fun ActionCoords.buildGitHubComparisonUrl(
-    version1: Version,
-    version2: Version,
-): String = "https://github.com/${this.owner}/${this.name}/compare/$version1...$version2#files_bucket"


Test patch:
diff --git a/automation/code-generator/src/test/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersionsTest.kt b/automation/code-generator/src/test/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersionsTest.kt
index aa5489d11..2a18fc7ee 100644
--- a/automation/code-generator/src/test/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersionsTest.kt
+++ b/automation/code-generator/src/test/kotlin/io/github/typesafegithub/workflows/codegenerator/versions/SuggestVersionsTest.kt
@@ -1,6 +1,10 @@
 package io.github.typesafegithub.workflows.codegenerator.versions
 
 import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
+import io.github.typesafegithub.workflows.actionbindinggenerator.domain.MetadataRevision
+import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Input
+import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Metadata
+import io.github.typesafegithub.workflows.actionbindinggenerator.metadata.Output
 import io.github.typesafegithub.workflows.codegenerator.model.Version
 import io.kotest.assertions.assertSoftly
 import io.kotest.core.spec.style.FunSpec
@@ -55,24 +59,67 @@ class SuggestVersionsTest : FunSpec({
         }
 
         test("New major version") {
-            assertSoftly {
+            @Suppress("UNUSED_PARAMETER")
+            fun ActionCoords.fetchMeta(metadataRevision: MetadataRevision): Metadata {
+                assert(owner == "test-owner")
+                assert(name == "test-name")
+                return when (this.version) {
+                    "v1" ->
+                        Metadata(
+                            name = "Test",
+                            description = "Test",
+                            inputs =
+                                mapOf(
+                                    "some-input" to Input(),
+                                    "input-will-be-removed-in-v2" to Input(),
+                                ),
+                            outputs =
+                                mapOf(
+                                    "some-outputs" to Output(),
+                                    "outputs-will-be-removed-in-v2" to Output(),
+                                ),
+                        )
+                    "v2", "v3", "v9", "v12" ->
+                        Metadata(
+                            name = "Test",
+                            description = "Test",
+                            inputs =
+                                mapOf(
+                                    "some-input" to Input(),
+                                    "new-input-in-v2" to Input(),
+                                ),
+                            outputs =
+                                mapOf(
+                                    "some-outputs" to Output(),
+                                    "new-input-in-v2" to Output(),
+                                ),
+                        )
+                    else -> error("No mocked response for version ${this.version}")
+                }
+            }
 
+            assertSoftly {
                 testCoords.suggestNewerVersion(
                     "v1".versions(),
                     "v1, v1.1.1, v2, v2.0.1, v3, v3.1.1".versions(),
+                    fetchMeta = ActionCoords::fetchMeta,
                 ) shouldBe "new version(s) available: [" +
-                    "v2 ([diff](https://github.com/test-owner/test-name/compare/v1...v2#files_bucket)), " +
-                    "v3 ([diff](https://github.com/test-owner/test-name/compare/v1...v3#files_bucket))]"
+                    "v2 (added inputs: [new-input-in-v2], removed inputs: [input-will-be-removed-in-v2], " +
+                    "added outputs: [new-input-in-v2], removed outputs: [outputs-will-be-removed-in-v2]), " +
+                    "v3 (added inputs: [new-input-in-v2], removed inputs: [input-will-be-removed-in-v2], " +
+                    "added outputs: [new-input-in-v2], removed outputs: [outputs-will-be-removed-in-v2])]"
 
                 testCoords.suggestNewerVersion(
                     "v2".versions(),
                     "v1.1.1, v2, v2.0.1, v3, v3.1.1".versions(),
-                ) shouldBe "new version(s) available: [v3 ([diff](https://github.com/test-owner/test-name/compare/v2...v3#files_bucket))]"
+                    fetchMeta = ActionCoords::fetchMeta,
+                ) shouldBe "new version(s) available: [v3 (added inputs: [], removed inputs: [], added outputs: [], removed outputs: [])]"
 
                 testCoords.suggestNewerVersion(
                     "v9".versions(),
                     "v12, v12.0.1".versions(),
-                ) shouldBe "new version(s) available: [v12 ([diff](https://github.com/test-owner/test-name/compare/v9...v12#files_bucket))]"
+                    fetchMeta = ActionCoords::fetchMeta,
+                ) shouldBe "new version(s) available: [v12 (added inputs: [], removed inputs: [], added outputs: [], removed outputs: [])]"
             }
         }
     }