Merge branch 'stable-3.12' into stable-3.13

* stable-3.12:
  Skip plugins with malformed JSON metadata

Change-Id: I6467122a3ccf9ded61e65c1ae90b94a0b2eecfcb
diff --git a/BUILD b/BUILD
index 9b85fed..51b324d 100644
--- a/BUILD
+++ b/BUILD
@@ -22,5 +22,6 @@
     visibility = ["//visibility:public"],
     deps = PLUGIN_TEST_DEPS + [
         ":plugin-manager__plugin",
+        "//lib/mockito",
     ],
 )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/manager/repository/JenkinsCiPluginsRepository.java b/src/main/java/com/googlesource/gerrit/plugins/manager/repository/JenkinsCiPluginsRepository.java
index d84eda5..48dac31 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/manager/repository/JenkinsCiPluginsRepository.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/manager/repository/JenkinsCiPluginsRepository.java
@@ -20,6 +20,7 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
+import com.google.gson.JsonSyntaxException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -253,13 +254,16 @@
                     jsonArtifact.get().getString("relativePath"))));
   }
 
-  private Optional<SmartJson> tryGetJson(String url) {
+  @VisibleForTesting
+  Optional<SmartJson> tryGetJson(String url) {
     try {
       return Optional.of(gsonProvider.get().get(url));
+    } catch (JsonSyntaxException jse) {
+      logger.atWarning().withCause(jse).log("Invalid JSON from %s", url);
     } catch (IOException e) {
       logger.atSevere().withCause(e).log("Cannot get JSON from %s", url);
-      return Optional.empty();
     }
+    return Optional.empty();
   }
 
   @VisibleForTesting
diff --git a/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java b/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java
index 2437d90..0e14aa1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/manager/repository/PluginsRepositoryTest.java
@@ -17,10 +17,14 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.TruthJUnit.assume;
 import static java.util.stream.Collectors.toList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.common.Version;
 import com.google.gerrit.server.config.SitePaths;
+import com.google.gson.JsonSyntaxException;
+import com.googlesource.gerrit.plugins.manager.gson.SmartGson;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -70,6 +74,16 @@
     assertThat(pluginRepo.list(Version.getVersion())).isNotEmpty();
   }
 
+  @Test
+  public void malformedPluginMetadataShouldBeIgnored() throws IOException {
+    String metadataUrl = "https://example.com/plugin.json";
+    SmartGson gson = mock(SmartGson.class);
+    when(gson.get(metadataUrl)).thenThrow(new JsonSyntaxException("Expected a JSON object"));
+    JenkinsCiPluginsRepository pluginRepo = new JenkinsCiPluginsRepository(() -> gson, null);
+
+    assertThat(pluginRepo.tryGetJson(metadataUrl)).isEmpty();
+  }
+
   private SitePaths prepareSiteDirWithReleaseWar() throws IOException {
     SitePaths site = new SitePaths(random());
     Path pathToReleaseWar = Path.of(getenv("TEST_SRCDIR"), getenv("TEST_WORKSPACE"), "release.war");