Fix NPE when calculating change actions ETag

Change I0ace488e44 introduced the mergeability status in the ETag
calulation so that when a change becomes (or is no longer) mergeable,
its associated ETag changes accordingly.

Mergeability however, despite being represented as a boolean value, is
modelled as `null` for changes that have a particular status, such as
'WIP' and 'Abandoned'.

Such `null` value cannot be passed directly to the ETag hasher, which
would throw an NPE otherwise.

Fix the NPE by accounting for `null` values when including mergeability
status in the ETag calculation.

Bug: Issue 297824101
Release-Notes: skip
Change-Id: Ic8f76172b60ff391857f978137db19f1292f55e0
diff --git a/java/com/google/gerrit/server/restapi/change/GetRevisionActions.java b/java/com/google/gerrit/server/restapi/change/GetRevisionActions.java
index 75f8e71..442f95e 100644
--- a/java/com/google/gerrit/server/restapi/change/GetRevisionActions.java
+++ b/java/com/google/gerrit/server/restapi/change/GetRevisionActions.java
@@ -38,6 +38,7 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.util.Map;
+import java.util.Optional;
 import org.eclipse.jgit.lib.Config;
 
 @Singleton
@@ -91,7 +92,8 @@
 
   private void hashMergeabilityStatus(Hasher h, Change.Id changeId) throws OrmException {
     for (ChangeData changeFromIndex : queryProvider.get().byLegacyChangeId(changeId)) {
-      h.putBoolean(changeFromIndex.isMergeable());
+      Optional<Boolean> isMergeable = Optional.ofNullable(changeFromIndex.isMergeable());
+      isMergeable.ifPresent(h::putBoolean);
     }
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ActionsIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ActionsIT.java
index c8b6642..431cc4a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ActionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ActionsIT.java
@@ -155,6 +155,15 @@
   }
 
   @Test
+  public void revisionActionsETagForWIPDoesNotThrow() throws Exception {
+    PushOneCommit.Result changeResult = createChange();
+    gApi.changes().id(changeResult.getChangeId()).setWorkInProgress();
+
+    String revisionActionsETag = getRevisionActionsETag(changeResult.getChangeId());
+    assertThat(revisionActionsETag).isNotNull();
+  }
+
+  @Test
   public void revisionActionsETag() throws Exception {
     String parent = createChange().getChangeId();
     String change = createChangeWithTopic().getChangeId();