public static List<ArtifactInformation> getArtifacts(List<String> stagingFiles) {
    ImmutableList.Builder<ArtifactInformation> artifactsBuilder = ImmutableList.builder();
    Set<String> deduplicatedStagingFiles = new LinkedHashSet<>(stagingFiles);
    for (String path : deduplicatedStagingFiles) {
      File file;
      String stagedName = null;
      if (path.contains("=")) {
        String[] components = path.split("=", 2);
        file = new File(components[1]);
        stagedName = components[0];
      } else {
        file = new File(path);
      }

      // Spurious items get added to the classpath, but ignoring silently can cause confusion.
      // Therefore, issue logs if a file does not exist before ignoring. The level will be warning
      // if they have a staged name, as those are likely to cause problems or unintended behavior
      // (e.g., dataflow-worker.jar, windmill_main).
      if (!file.exists()) {
        if (stagedName != null) {
          LOG.warn(
              "Stage Artifact '{}' with the name '{}' was not found, staging will be ignored.",
              file,
              stagedName);
        } else {
          LOG.info("Stage Artifact '{}' was not found, staging will be ignored.", file);
        }
        continue;
      }

      ArtifactInformation.Builder artifactBuilder = ArtifactInformation.newBuilder();
      artifactBuilder.setTypeUrn(BeamUrns.getUrn(StandardArtifacts.Types.FILE));
      artifactBuilder.setRoleUrn(BeamUrns.getUrn(StandardArtifacts.Roles.STAGING_TO));
      HashCode hashCode;
      if (file.isDirectory()) {
        File zippedFile;
        try {
          zippedFile = zipDirectory(file);
          hashCode = Files.asByteSource(zippedFile).hash(Hashing.sha256());
        } catch (IOException e) {
          throw new RuntimeException(e);
        }

        artifactBuilder.setTypePayload(
            RunnerApi.ArtifactFilePayload.newBuilder()
                .setPath(zippedFile.getPath())
                .setSha256(hashCode.toString())
                .build()
                .toByteString());

      } else {
        try {
          hashCode = Files.asByteSource(file).hash(Hashing.sha256());
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
        artifactBuilder.setTypePayload(
            RunnerApi.ArtifactFilePayload.newBuilder()
                .setPath(file.getPath())
                .setSha256(hashCode.toString())
                .build()
                .toByteString());
      }
      if (stagedName == null) {
        stagedName = createStagingFileName(file, hashCode);
      }
      artifactBuilder.setRolePayload(
          RunnerApi.ArtifactStagingToRolePayload.newBuilder()
              .setStagedName(stagedName)
              .build()
              .toByteString());
      artifactsBuilder.add(artifactBuilder.build());
    }
    return artifactsBuilder.build();
  }
@Test
  public void testGetArtifactsBadFileLogsInfo() throws Exception {
    File file1 = File.createTempFile("file1-", ".txt");
    file1.deleteOnExit();

    List<ArtifactInformation> artifacts =
        Environments.getArtifacts(ImmutableList.of(file1.getAbsolutePath(), "spurious_file"));

    assertThat(artifacts, hasSize(1));
    expectedLogs.verifyInfo("'spurious_file' was not found");
  }