Encode remaining ActionExecution failures with FailureDetails

This removes the last uses of undetailed ActionExecutionException
constructors by adding details to {Test,User}ExecException.

RELNOTES: None.
PiperOrigin-RevId: 318143448
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
index 92d1e32..afc1562 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
@@ -356,12 +356,9 @@
         ExecException execEx =
             new EnvironmentalExecException(
                 ioEx,
-                FailureDetail.newBuilder()
-                    .setMessage("Failed to delete output files after incomplete download")
-                    .setRemoteExecution(
-                        RemoteExecution.newBuilder()
-                            .setCode(Code.INCOMPLETE_OUTPUT_DOWNLOAD_CLEANUP_FAILURE))
-                    .build());
+                createFailureDetail(
+                    "Failed to delete output files after incomplete download",
+                    Code.INCOMPLETE_OUTPUT_DOWNLOAD_CLEANUP_FAILURE));
         execEx.addSuppressed(e);
         throw execEx;
       }
@@ -968,12 +965,13 @@
 
     private void illegalOutput(Path what) throws ExecException {
       String kind = what.isSymbolicLink() ? "symbolic link" : "special file";
-      throw new UserExecException(
+      String message =
           String.format(
               "Output %s is a %s. Only regular files and directories may be "
                   + "uploaded to a remote cache. "
                   + "Change the file type or use --remote_allow_symlink_upload.",
-              what.relativeTo(execRoot), kind));
+              what.relativeTo(execRoot), kind);
+      throw new UserExecException(createFailureDetail(message, Code.ILLEGAL_OUTPUT));
     }
   }
 
@@ -983,6 +981,13 @@
     cacheProtocol.close();
   }
 
+  private static FailureDetail createFailureDetail(String message, Code detailedCode) {
+    return FailureDetail.newBuilder()
+        .setMessage(message)
+        .setRemoteExecution(RemoteExecution.newBuilder().setCode(detailedCode))
+        .build();
+  }
+
   /**
    * Creates an {@link OutputStream} that isn't actually opened until the first data is written.
    * This is useful to only have as many open file descriptors as necessary at a time to avoid