From 1e7b29bc4db8cbcfc468e3df4a649113efa3b876 Mon Sep 17 00:00:00 2001
From: Da Risk <da_risk@geekorum.com>
Date: Wed, 17 May 2023 16:42:10 -0400
Subject: [PATCH 1/2] oss-license-plugin: sort ArtifactInfo into list

This should ensure that the output of third_party_licenses and third_party_licenses_metadata is sorted.
Sorting the output will make it reproducible regardless of the input ordering.
---
 .../oss/licenses/plugin/DependencyTask.groovy   |  5 +++--
 .../gms/oss/licenses/plugin/LicensesTask.groovy |  4 ++--
 .../oss/licenses/plugin/DependencyTaskTest.java | 17 ++++++++++++-----
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/DependencyTask.groovy b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/DependencyTask.groovy
index c7848735..5dbfbb30 100644
--- a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/DependencyTask.groovy
+++ b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/DependencyTask.groovy
@@ -76,7 +76,7 @@ abstract class DependencyTask extends DefaultTask {
         } as AppDependencies
     }
 
-    private static Set<ArtifactInfo> convertDependenciesToArtifactInfo(
+    private static List<ArtifactInfo> convertDependenciesToArtifactInfo(
             AppDependencies appDependencies
     ) {
         return appDependencies.libraryList.stream()
@@ -88,7 +88,8 @@ abstract class DependencyTask extends DefaultTask {
                             library.mavenLibrary.version
                     )
                 }
-                .collect(Collectors.toUnmodifiableSet())
+                .sorted(Comparator.comparing { it.toString() })
+                .collect(Collectors.toUnmodifiableList())
     }
 
     private static void initOutput(File outputDir) {
diff --git a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
index 851846b5..43db6652 100644
--- a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
+++ b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
@@ -107,14 +107,14 @@ abstract class LicensesTask extends DefaultTask {
         writeMetadata()
     }
 
-    private static Set<ArtifactInfo> loadDependenciesJson(File jsonFile) {
+    private static List<ArtifactInfo> loadDependenciesJson(File jsonFile) {
         def allDependencies = new JsonSlurper().parse(jsonFile)
         def artifactInfoSet = new HashSet<ArtifactInfo>()
         for (entry in allDependencies) {
             ArtifactInfo artifactInfo = artifactInfoFromEntry(entry)
             artifactInfoSet.add(artifactInfo)
         }
-        artifactInfoSet.asImmutable()
+        artifactInfoSet.toList().asImmutable()
     }
 
     private void addDebugLicense() {
diff --git a/oss-licenses-plugin/src/test/java/com/google/android/gms/oss/licenses/plugin/DependencyTaskTest.java b/oss-licenses-plugin/src/test/java/com/google/android/gms/oss/licenses/plugin/DependencyTaskTest.java
index e35a5490..50760521 100644
--- a/oss-licenses-plugin/src/test/java/com/google/android/gms/oss/licenses/plugin/DependencyTaskTest.java
+++ b/oss-licenses-plugin/src/test/java/com/google/android/gms/oss/licenses/plugin/DependencyTaskTest.java
@@ -29,6 +29,9 @@
 import java.io.OutputStream;
 import java.lang.reflect.Type;
 import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
 import org.gradle.api.Project;
 import org.gradle.testfixtures.ProjectBuilder;
 import org.junit.Before;
@@ -84,8 +87,8 @@ public void testAction_valuesConvertedToJson() throws Exception {
     File outputJson = new File(outputDir, "test.json");
     dependencyTask.getDependenciesJson().set(outputJson);
     ImmutableSet<ArtifactInfo> expectedArtifacts = ImmutableSet.of(
-        new ArtifactInfo("org.group.id", "artifactId", "1.0.0"),
-        new ArtifactInfo("org.group.other", "other-artifact", "3.2.1")
+        new ArtifactInfo("org.group.other", "other-artifact", "3.2.1"),
+        new ArtifactInfo("org.group.id", "artifactId", "1.0.0")
     );
     AppDependencies appDependencies = createAppDependencies(expectedArtifacts);
     File protoFile = writeAppDependencies(appDependencies, temporaryFolder.newFile());
@@ -102,8 +105,8 @@ public void testAction_withNonMavenDeps_nonMavenDepsIgnored() throws Exception {
     File outputJson = new File(outputDir, "test.json");
     dependencyTask.getDependenciesJson().set(outputJson);
     ImmutableSet<ArtifactInfo> expectedArtifacts = ImmutableSet.of(
-        new ArtifactInfo("org.group.id", "artifactId", "1.0.0"),
-        new ArtifactInfo("org.group.other", "other-artifact", "3.2.1")
+        new ArtifactInfo("org.group.other", "other-artifact", "3.2.1"),
+        new ArtifactInfo("org.group.id", "artifactId", "1.0.0")
     );
     AppDependencies appDependencies = createAppDependencies(expectedArtifacts).toBuilder()
         .addLibrary(Library.getDefaultInstance()) // There aren't any other library types supported.
@@ -131,11 +134,15 @@ public void testAction_depFileAbsent_writesAbsentDep() throws Exception {
   private void verifyExpectedDependencies(ImmutableSet<ArtifactInfo> expectedArtifacts,
       File outputJson) throws Exception {
     Gson gson = new Gson();
+    List<ArtifactInfo> expectedArtifactsSorted = expectedArtifacts
+            .stream()
+            .sorted(Comparator.comparing(ArtifactInfo::toString))
+            .collect(Collectors.toUnmodifiableList());
     try (FileReader reader = new FileReader(outputJson)) {
       Type collectionOfArtifactInfo = new TypeToken<Collection<ArtifactInfo>>() {
       }.getType();
       Collection<ArtifactInfo> jsonArtifacts = gson.fromJson(reader, collectionOfArtifactInfo);
-      assertThat(jsonArtifacts).containsExactlyElementsIn(expectedArtifacts);
+      assertThat(jsonArtifacts).containsExactlyElementsIn(expectedArtifactsSorted).inOrder();
     }
   }
 

From 0ae426b1fe52ef70770d10050402413a22bd8dba Mon Sep 17 00:00:00 2001
From: Da Risk <da_risk@geekorum.com>
Date: Fri, 19 May 2023 21:22:26 -0400
Subject: [PATCH 2/2] oss-license-plugin: Sort dependencies loaded for
 LicensesTask

---
 .../android/gms/oss/licenses/plugin/LicensesTask.groovy      | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
index 43db6652..7dac8aae 100644
--- a/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
+++ b/oss-licenses-plugin/src/main/groovy/com/google/android/gms/oss/licenses/plugin/LicensesTask.groovy
@@ -25,6 +25,7 @@ import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import org.slf4j.LoggerFactory
 
+import java.util.stream.Collectors
 import java.util.zip.ZipEntry
 import java.util.zip.ZipFile
 
@@ -114,7 +115,9 @@ abstract class LicensesTask extends DefaultTask {
             ArtifactInfo artifactInfo = artifactInfoFromEntry(entry)
             artifactInfoSet.add(artifactInfo)
         }
-        artifactInfoSet.toList().asImmutable()
+        artifactInfoSet.stream()
+                .sorted(Comparator.comparing { it.toString() })
+                .collect(Collectors.toUnmodifiableList())
     }
 
     private void addDebugLicense() {
