From ac736b0c9872e835d7b59b673b0c9f256db97546 Mon Sep 17 00:00:00 2001
From: brianwyka
Date: Sat, 11 Dec 2021 16:22:13 -0500
Subject: [PATCH 01/31] Remote repository scanning improvements progress
---
.../cli/AbstractRemoteScanCommand.java | 19 +++----
.../sourcehawk/cli/BitbucketScanCommand.java | 37 +++++++------
.../optum/sourcehawk/cli/CommandOptions.java | 11 +++-
.../sourcehawk/cli/GithubScanCommand.java | 37 ++++++-------
.../optum/sourcehawk/core/data/RemoteRef.java | 49 +++--------------
.../BitbucketRepositoryFileReader.java | 52 ------------------
.../GithubRepositoryFileReader.java | 54 -------------------
.../repository/LocalRepositoryFileReader.java | 6 +++
.../RemoteRepositoryFileReader.java | 51 +++++++++---------
.../core/repository/RepositoryFileReader.java | 8 +++
.../sourcehawk/exec/ExecOptionsSpec.groovy | 2 +-
11 files changed, 101 insertions(+), 225 deletions(-)
delete mode 100644 core/src/main/java/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReader.java
delete mode 100644 core/src/main/java/com/optum/sourcehawk/core/repository/GithubRepositoryFileReader.java
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java b/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
index daa1855..cdae269 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
@@ -52,21 +52,14 @@ public Integer call() {
.isPresent();
val remoteRef = validateAndParseRemoteRef();
execOptionsBuilder.remoteRef(remoteRef);
+ val repositoryFileReader = createRepositoryFileReader(remoteRef);
+ execOptionsBuilder.repositoryFileReader(repositoryFileReader);
if (StringUtils.equals(SourcehawkConstants.DEFAULT_CONFIG_FILE_NAME, parentExecOptions.getConfigurationFileLocation()) && !configFileProvided) {
- execOptionsBuilder.configurationFileLocation(constructRemoteConfigFileLocation(remoteRef));
+ execOptionsBuilder.configurationFileLocation(repositoryFileReader.getAbsoluteLocation(SourcehawkConstants.DEFAULT_CONFIG_FILE_NAME));
}
- execOptionsBuilder.repositoryFileReader(createRepositoryFileReader(remoteRef)).build();
return parentCommand.call(execOptionsBuilder.build());
}
- /**
- * Construct the remote config file location
- *
- * @param remoteRef the remote reference
- * @return the config file remote location
- */
- protected abstract String constructRemoteConfigFileLocation(final RemoteRef remoteRef);
-
/**
* Create the repository file reader based off the remote reference
*
@@ -76,11 +69,11 @@ public Integer call() {
protected abstract RepositoryFileReader createRepositoryFileReader(final RemoteRef remoteRef);
/**
- * Get the remote reference descriptor
+ * Get the raw remote reference
*
- * @return the raw remote reference descriptor
+ * @return the raw remote reference
*/
- protected abstract Pair getRawRemoteReference();
+ protected abstract Pair getRawRemoteReference();
/**
* Parse the coordinates to github options
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/BitbucketScanCommand.java b/cli/src/main/java/com/optum/sourcehawk/cli/BitbucketScanCommand.java
index 30c254b..c4caf44 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/BitbucketScanCommand.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/BitbucketScanCommand.java
@@ -1,14 +1,15 @@
package com.optum.sourcehawk.cli;
-import com.optum.sourcehawk.core.constants.SourcehawkConstants;
import com.optum.sourcehawk.core.data.Pair;
import com.optum.sourcehawk.core.data.RemoteRef;
-import com.optum.sourcehawk.core.repository.BitbucketRepositoryFileReader;
+import com.optum.sourcehawk.core.repository.RemoteRepositoryFileReader;
import com.optum.sourcehawk.core.repository.RepositoryFileReader;
import lombok.val;
import picocli.CommandLine;
-import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
import java.util.Optional;
/**
@@ -25,6 +26,9 @@
)
public class BitbucketScanCommand extends AbstractRemoteScanCommand {
+ private static final String DEFAULT_BASE_URL = "https://bitbucket.org";
+ private static final String DEFAULT_REF = "main";
+
/**
* The Bitbucket options
*/
@@ -44,25 +48,24 @@ public static void main(final String... args) {
/** {@inheritDoc} */
@Override
protected RepositoryFileReader createRepositoryFileReader(final RemoteRef remoteRef) {
- if (bitbucket.serverUrl != null) {
- return new BitbucketRepositoryFileReader(bitbucket.token, bitbucket.serverUrl.toString(), remoteRef);
+ val rawFileUrlTemplate = Optional.ofNullable(bitbucket.serverUrl)
+ .map(bitbucketServerUrl -> String.format("%s/rest/api/1.0/projects/%s/repos/%s/raw/%%s?at=%s",
+ bitbucketServerUrl, remoteRef.getNamespace(), remoteRef.getRepository(), remoteRef.getRef()))
+ .orElseGet(() -> String.format("%s/api/2.0/repositories/%s/%s/src/%s/%%s", DEFAULT_BASE_URL, remoteRef.getNamespace(), remoteRef.getRepository(), remoteRef.getRef()));
+ val requestProperties = new HashMap();
+ requestProperties.put("Accept", "text/plain");
+ if (bitbucket.token != null) {
+ val authScheme = Optional.ofNullable(bitbucket.authScheme)
+ .orElse(CommandOptions.Bitbucket.DEFAULT_AUTH_SCHEME);
+ requestProperties.put("Authorization", String.format("%s %s", authScheme, bitbucket.token));
}
- return new BitbucketRepositoryFileReader(bitbucket.token, remoteRef);
- }
-
- /** {@inheritDoc} */
- @Override
- protected Pair getRawRemoteReference() {
- return Pair.of(RemoteRef.Type.BITBUCKET, bitbucket.remoteReference);
+ return new RemoteRepositoryFileReader(rawFileUrlTemplate, requestProperties);
}
/** {@inheritDoc} */
@Override
- protected String constructRemoteConfigFileLocation(final RemoteRef remoteRef) {
- val bitbucketBaseUrl = Optional.ofNullable(bitbucket.serverUrl)
- .map(URL::toString)
- .orElseGet(RemoteRef.Type.BITBUCKET::getBaseUrl);
- return BitbucketRepositoryFileReader.constructBaseUrl(remoteRef, bitbucketBaseUrl) + SourcehawkConstants.DEFAULT_CONFIG_FILE_NAME;
+ protected Pair getRawRemoteReference() {
+ return Pair.of(bitbucket.remoteReference, DEFAULT_REF);
}
}
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/CommandOptions.java b/cli/src/main/java/com/optum/sourcehawk/cli/CommandOptions.java
index ceba6c5..d25f175 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/CommandOptions.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/CommandOptions.java
@@ -152,6 +152,15 @@ static class Bitbucket {
)
String token;
+ @CommandLine.Option(
+ names = {"-a", "--auth-scheme"},
+ paramLabel = "auth-scheme",
+ defaultValue = DEFAULT_AUTH_SCHEME,
+ description = "The authorization scheme to use (either Bearer or Basic). If Basic, the provided token must be base64 encoded."
+ )
+ String authScheme;
+ static final String DEFAULT_AUTH_SCHEME = "Bearer";
+
@CommandLine.Option(
names = {"-S", "--server-url"},
paramLabel = "bitbucket-server-url",
@@ -162,7 +171,7 @@ static class Bitbucket {
@CommandLine.Parameters(
paramLabel = REMOTE_REFERENCE_LABEL,
description = "The Bitbucket remote reference - project/repo@ref combination, "
- + "i.e - project/repo, project/repo@master, project/repo@v1.4, or project/repo@a6de43fa51c",
+ + "i.e - project/repo, project/repo@main, project/repo@v1.4, or project/repo@a6de43fa51c",
arity = "1"
)
String remoteReference;
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/GithubScanCommand.java b/cli/src/main/java/com/optum/sourcehawk/cli/GithubScanCommand.java
index 784cf1f..b233902 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/GithubScanCommand.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/GithubScanCommand.java
@@ -1,14 +1,13 @@
package com.optum.sourcehawk.cli;
-import com.optum.sourcehawk.core.constants.SourcehawkConstants;
import com.optum.sourcehawk.core.data.Pair;
import com.optum.sourcehawk.core.data.RemoteRef;
-import com.optum.sourcehawk.core.repository.GithubRepositoryFileReader;
+import com.optum.sourcehawk.core.repository.RemoteRepositoryFileReader;
import com.optum.sourcehawk.core.repository.RepositoryFileReader;
import lombok.val;
import picocli.CommandLine;
-import java.net.URL;
+import java.util.HashMap;
import java.util.Optional;
/**
@@ -25,6 +24,10 @@
)
public class GithubScanCommand extends AbstractRemoteScanCommand {
+ private static final String DEFAULT_BASE_URL = "raw.githubusercontent.com";
+ private static final String DEFAULT_REF = "main";
+ private static final String AUTHORIZATION_TOKEN_PREFIX = "Bearer";
+
/**
* The github options
*/
@@ -44,28 +47,22 @@ public static void main(final String... args) {
/** {@inheritDoc} */
@Override
protected RepositoryFileReader createRepositoryFileReader(final RemoteRef remoteRef) {
- if (github.enterpriseUrl != null) {
- return new GithubRepositoryFileReader(github.token, github.enterpriseUrl.toString(), remoteRef);
+ val baseUrl = Optional.ofNullable(github.enterpriseUrl)
+ .map(githubEnterpriseUrl -> String.format("%s/raw", github.enterpriseUrl))
+ .orElse(DEFAULT_BASE_URL);
+ val rawFileUrlTemplate = String.format("%s/%s/%s/%s/%%s", baseUrl, remoteRef.getNamespace(), remoteRef.getRepository(), remoteRef.getRef());
+ val requestProperties = new HashMap();
+ requestProperties.put("Accept", "text/plain");
+ if (github.token != null) {
+ requestProperties.put("Authorization", String.format("%s %s", AUTHORIZATION_TOKEN_PREFIX, github.token));
}
- return new GithubRepositoryFileReader(github.token, remoteRef);
- }
-
- /** {@inheritDoc} */
- @Override
- protected Pair getRawRemoteReference() {
- return Pair.of(RemoteRef.Type.GITHUB, github.remoteReference);
+ return new RemoteRepositoryFileReader(rawFileUrlTemplate, requestProperties);
}
/** {@inheritDoc} */
@Override
- protected String constructRemoteConfigFileLocation(final RemoteRef remoteRef) {
- val githubEnterpriseUrl = Optional.ofNullable(github.enterpriseUrl).map(URL::toString);
- val githubRepoBaseUrl = GithubRepositoryFileReader.constructBaseUrl(
- githubEnterpriseUrl.orElseGet(RemoteRef.Type.GITHUB::getBaseUrl),
- githubEnterpriseUrl.isPresent(),
- remoteRef
- );
- return githubRepoBaseUrl + SourcehawkConstants.DEFAULT_CONFIG_FILE_NAME;
+ protected Pair getRawRemoteReference() {
+ return Pair.of(github.remoteReference, DEFAULT_REF);
}
}
diff --git a/core/src/main/java/com/optum/sourcehawk/core/data/RemoteRef.java b/core/src/main/java/com/optum/sourcehawk/core/data/RemoteRef.java
index c17c32e..09f179e 100644
--- a/core/src/main/java/com/optum/sourcehawk/core/data/RemoteRef.java
+++ b/core/src/main/java/com/optum/sourcehawk/core/data/RemoteRef.java
@@ -25,13 +25,7 @@ public class RemoteRef {
private static final String PARSE_ERROR_PREFIX = "Invalid remote reference";
/**
- * The type of the remote reference
- */
- @NonNull
- Type type;
-
- /**
- * The remote namespace, such as Github owner / organization, or Bitbucket project
+ * The remote namespace, such as Github owner / organization, or Bitbucket user / project
*/
@NonNull
String namespace;
@@ -51,20 +45,20 @@ public class RemoteRef {
/**
* Create the remote ref from the type and raw reference
*
- * @param type the type of the remote ref
* @param rawRemoteRef the raw remote reference
+ * @param defaultRef the default ref to use if none provided
* @return the remote reference
*/
- public static RemoteRef parse(final Type type, final String rawRemoteRef) {
+ public static RemoteRef parse(final String rawRemoteRef, final String defaultRef) {
if (rawRemoteRef.indexOf(COORDINATES_DELIMITER) == -1) {
- val message = String.format("%s, must contain '%s' separator between %s and repository", PARSE_ERROR_PREFIX, COORDINATES_DELIMITER, type.getNamespaceType());
+ val message = String.format("%s, must contain '%s' separator between repository coordinates", PARSE_ERROR_PREFIX, COORDINATES_DELIMITER);
throw new IllegalArgumentException(message);
}
val remoteRefBuilder = builder();
final String rawCoordinates;
if (rawRemoteRef.indexOf(REF_DELIMITER) == -1) {
rawCoordinates = rawRemoteRef;
- remoteRefBuilder.ref(type.getDefaultBranch());
+ remoteRefBuilder.ref(defaultRef);
} else {
val refDelimiterIndex= rawRemoteRef.indexOf(REF_DELIMITER);
rawCoordinates = rawRemoteRef.substring(0, refDelimiterIndex);
@@ -77,7 +71,7 @@ public static RemoteRef parse(final Type type, final String rawRemoteRef) {
if (coordinates.length < 2) {
throw new IllegalArgumentException(PARSE_ERROR_PREFIX + ", repository must not be empty");
}
- return remoteRefBuilder.type(type)
+ return remoteRefBuilder
.namespace(coordinates[0])
.repository(coordinates[1])
.build();
@@ -86,36 +80,7 @@ public static RemoteRef parse(final Type type, final String rawRemoteRef) {
/** {@inheritDoc} */
@Override
public String toString() {
- return String.format("[%s] %s%s%s%s%s", type.name(), namespace, COORDINATES_DELIMITER, repository, REF_DELIMITER, ref);
- }
-
- /**
- * The type of the remote reference
- *
- * @author Brian Wyka
- */
- @Getter
- @AllArgsConstructor(access = AccessLevel.PRIVATE)
- public enum Type {
-
- BITBUCKET("https://bitbucket.org", "master", "project"),
- GITHUB("https://raw.githubusercontent.com", "main", "owner");
-
- /**
- * The base URL
- */
- private final String baseUrl;
-
- /**
- * The name of the default branch
- */
- private final String defaultBranch;
-
- /**
- * The namespace type
- */
- private final String namespaceType;
-
+ return String.format("%s%s%s%s%s", namespace, COORDINATES_DELIMITER, repository, REF_DELIMITER, ref);
}
}
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReader.java
deleted file mode 100644
index ceb9ccf..0000000
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReader.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.optum.sourcehawk.core.repository;
-
-import com.optum.sourcehawk.core.data.RemoteRef;
-import lombok.NonNull;
-import lombok.val;
-
-/**
- * A {@link RemoteRepositoryFileReader} implementation which reads files from remote Bitbucket repositories
- *
- * @author Brian Wyka
- */
-public class BitbucketRepositoryFileReader extends RemoteRepositoryFileReader {
-
- /**
- * The authorization token prefix
- */
- private static final String AUTHORIZATION_TOKEN_PREFIX = "Bearer ";
-
- /**
- * Constructs the Bitbucket repository file reader
- *
- * @param token the token
- * @param bitbucketBaseUrl the Bitbucket base URL
- * @param remoteRef the remote ref
- */
- public BitbucketRepositoryFileReader(final String token, @NonNull final String bitbucketBaseUrl, final RemoteRef remoteRef) {
- super(constructBaseUrl(remoteRef, bitbucketBaseUrl), constructRequestProperties(AUTHORIZATION_TOKEN_PREFIX, token));
- }
-
- /**
- * Constructs an instance of this reader with the provided project, repo, and ref
- *
- * @param token the github token (optional)
- * @param remoteRef the remote reference
- */
- public BitbucketRepositoryFileReader(final String token, @NonNull final RemoteRef remoteRef) {
- this(token, RemoteRef.Type.BITBUCKET.getBaseUrl(), remoteRef);
- }
-
- /**
- * Construct the base URL of the Bitbucket repository based on the provided project, repo, and ref
- *
- * @param remoteRef the remote reference
- * @param bitbucketBaseUrl the base URL
- * @return the constructed base URL with a trailing {@value #SEPARATOR}
- */
- public static String constructBaseUrl(final RemoteRef remoteRef, final String bitbucketBaseUrl) {
- val baseUrl = bitbucketBaseUrl.endsWith(SEPARATOR) ? bitbucketBaseUrl.substring(0, bitbucketBaseUrl.length() - 1) : bitbucketBaseUrl;
- return String.format("%s/%s/%s/raw/%s/", baseUrl, remoteRef.getNamespace(), remoteRef.getRepository(), remoteRef.getRef());
- }
-
-}
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/GithubRepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/GithubRepositoryFileReader.java
deleted file mode 100644
index dabcf8e..0000000
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/GithubRepositoryFileReader.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.optum.sourcehawk.core.repository;
-
-import com.optum.sourcehawk.core.data.RemoteRef;
-import lombok.NonNull;
-import lombok.val;
-
-/**
- * A {@link RemoteRepositoryFileReader} implementation which reads files from remote Github repositories
- *
- * @author Brian Wyka
- */
-public class GithubRepositoryFileReader extends RemoteRepositoryFileReader {
-
- /**
- * The authorization token prefix
- */
- private static final String AUTHORIZATION_TOKEN_PREFIX = "token ";
-
- /**
- * Constructs an instance of this reader with the provided Github Enterprise URL
- *
- * @param token the github token (optional)
- * @param githubEnterpriseUrl the Github enterprise URL
- * @param remoteRef the remote reference
- */
- public GithubRepositoryFileReader(final String token, @NonNull final String githubEnterpriseUrl, @NonNull final RemoteRef remoteRef) {
- super(constructBaseUrl(githubEnterpriseUrl, true, remoteRef), constructRequestProperties(AUTHORIZATION_TOKEN_PREFIX, token));
- }
-
- /**
- * Constructs an instance of this reader with the provided owner, repo, and ref
- *
- * @param token the github token (optional)
- * @param remoteRef the remote reference
- */
- public GithubRepositoryFileReader(final String token, @NonNull final RemoteRef remoteRef) {
- super(constructBaseUrl(RemoteRef.Type.GITHUB.getBaseUrl(), false, remoteRef), constructRequestProperties(AUTHORIZATION_TOKEN_PREFIX, token));
- }
-
- /**
- * Construct the base URL of the Github repository based on the provided owner, repo, and ref
- *
- * @param githubUrl the Github URL
- * @param githubEnterprise true if Github Enterprise, false otherwise
- * @param remoteRef the remote reference
- * @return the constructed base URL with a trailing {@value #SEPARATOR}
- */
- public static String constructBaseUrl(final String githubUrl, final boolean githubEnterprise, final RemoteRef remoteRef) {
- val baseUrl = githubUrl.endsWith(SEPARATOR) ? githubUrl.substring(0, githubUrl.length() - 1) : githubUrl;
- val githubBaseUrl = githubEnterprise ? baseUrl + "/raw" : baseUrl;
- return String.format("%s/%s/%s/%s/", githubBaseUrl, remoteRef.getNamespace(), remoteRef.getRepository(), remoteRef.getRef());
- }
-
-}
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/LocalRepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/LocalRepositoryFileReader.java
index 802d58d..c4f88c6 100644
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/LocalRepositoryFileReader.java
+++ b/core/src/main/java/com/optum/sourcehawk/core/repository/LocalRepositoryFileReader.java
@@ -59,6 +59,12 @@ public Optional read(@NonNull final String repositoryFilePath) thro
return getInputStream(directory.resolve(Paths.get(repositoryFilePath)));
}
+ /** {@inheritDoc} */
+ @Override
+ public String getAbsoluteLocation(final String repositoryFilePath) {
+ return directory.resolve(Paths.get(repositoryFilePath)).toAbsolutePath().toString();
+ }
+
/**
* Get the {@link InputStream} from the {@link File} reference
*
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
index 76bda54..d7a5440 100644
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
+++ b/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
@@ -16,21 +16,21 @@
/**
* A remote repository file reader which treats the repository file paths relative
- * to the base URL provided during construction
+ * to the raw file URL template provided during construction
*
* @author Brian Wyka
*/
-abstract class RemoteRepositoryFileReader implements RepositoryFileReader {
+public final class RemoteRepositoryFileReader implements RepositoryFileReader {
/**
* URL Separator
*/
- protected static final String SEPARATOR = "/";
+ private static final String SEPARATOR = "/";
/**
- * The base URL to read from
+ * The raw file URL template. Takes one parameter: The path of the file in the repository
*/
- private final String baseUrl;
+ private final String rawFileUrlTemplate;
/**
* The required request properties
@@ -45,31 +45,27 @@ abstract class RemoteRepositoryFileReader implements RepositoryFileReader {
/**
* Constructs an instance of this reader with the provided base URL
*
- * @param baseUrl the base URL
+ * @param rawFileUrlTemplate the raw file URL template
* @param requestProperties the request properties required for connection
*/
- protected RemoteRepositoryFileReader(@NonNull final String baseUrl, final Map requestProperties) {
- if (baseUrl.endsWith(SEPARATOR)) {
- this.baseUrl = baseUrl;
- } else {
- this.baseUrl = baseUrl + SEPARATOR;
- }
+ public RemoteRepositoryFileReader(@NonNull final String rawFileUrlTemplate, final Map requestProperties) {
+ this.rawFileUrlTemplate = rawFileUrlTemplate;
this.requestProperties = requestProperties;
}
/**
* Constructs an instance of this reader with the provided base URL
*
- * @param baseUrl the base URL
+ * @param rawFileUrlTemplate the base URL
*/
- protected RemoteRepositoryFileReader(@NonNull final String baseUrl) {
- this(baseUrl, Collections.emptyMap());
+ protected RemoteRepositoryFileReader(@NonNull final String rawFileUrlTemplate) {
+ this(rawFileUrlTemplate, Collections.emptyMap());
}
/** {@inheritDoc} */
@Override
public boolean exists(final String repositoryFilePath) throws IOException {
- val absoluteUrl = constructAbsoluteUrl(baseUrl, repositoryFilePath);
+ val absoluteUrl = new URL(constructAbsoluteLocation(rawFileUrlTemplate, repositoryFilePath));
val absoluteUrlString = absoluteUrl.toString();
if (urlExistenceCache.containsKey(absoluteUrlString)) {
return urlExistenceCache.get(absoluteUrlString);
@@ -82,7 +78,7 @@ public boolean exists(final String repositoryFilePath) throws IOException {
/** {@inheritDoc} */
@Override
public Optional read(final String repositoryFilePath) throws IOException {
- val absoluteUrl = constructAbsoluteUrl(baseUrl, repositoryFilePath);
+ val absoluteUrl = new URL(constructAbsoluteLocation(rawFileUrlTemplate, repositoryFilePath));
if (exists(repositoryFilePath)) {
val httpUrlConnection = (HttpURLConnection) absoluteUrl.openConnection();
requestProperties.forEach(httpUrlConnection::setRequestProperty);
@@ -91,6 +87,12 @@ public Optional read(final String repositoryFilePath) throws IOExce
return Optional.empty();
}
+ /** {@inheritDoc} */
+ @Override
+ public String getAbsoluteLocation(final String repositoryFilePath) {
+ return constructAbsoluteLocation(rawFileUrlTemplate, repositoryFilePath);
+ }
+
/**
* Get the input stream from the {@link HttpURLConnection}
*
@@ -121,22 +123,21 @@ private boolean urlExists(final URL url) throws IOException {
}
/**
- * Construct the absolute URL to the remote file
+ * Construct the absolute location to the remote file
*
- * @param baseUrl the repository base URL
+ * @param rawFileUrlTemplate the raw file URL template
* @param repositoryFilePath the repository file path
- * @return the absolute URL to the file
- * @throws IOException if the URL is malformed
+ * @return the absolute location to the repository file
*/
- private static URL constructAbsoluteUrl(final String baseUrl, final String repositoryFilePath) throws IOException {
+ private static String constructAbsoluteLocation(final String rawFileUrlTemplate, final String repositoryFilePath) {
if (repositoryFilePath.startsWith(SEPARATOR)) {
- return new URL(baseUrl + repositoryFilePath.substring(1));
+ return String.format(rawFileUrlTemplate, repositoryFilePath.substring(1));
}
- return new URL(baseUrl + repositoryFilePath);
+ return String.format(rawFileUrlTemplate, repositoryFilePath);
}
/**
- * Construct the request properties for the provided github token
+ * Construct the request properties for the provided authorization token
*
* @param authorizationPrefix the authorization request property prefix
* @param authorizationToken the authorization token
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/RepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/RepositoryFileReader.java
index 1fabc10..ca4c43e 100644
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/RepositoryFileReader.java
+++ b/core/src/main/java/com/optum/sourcehawk/core/repository/RepositoryFileReader.java
@@ -38,4 +38,12 @@ default boolean supportsGlobPatterns() {
*/
Optional read(final String repositoryFilePath) throws IOException;
+ /**
+ * Get a string representation of the absolute location of {@code repositoryFilePath}
+ *
+ * @param repositoryFilePath the repository file path
+ * @return the absolute location
+ */
+ String getAbsoluteLocation(final String repositoryFilePath);
+
}
diff --git a/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy b/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
index 0ca74cc..91bd09a 100644
--- a/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
+++ b/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
@@ -1,7 +1,7 @@
package com.optum.sourcehawk.exec
import com.optum.sourcehawk.core.data.RemoteRef
-import com.optum.sourcehawk.core.repository.GithubRepositoryFileReader
+
import com.optum.sourcehawk.core.repository.LocalRepositoryFileReader
import com.optum.sourcehawk.core.data.Verbosity
import spock.lang.Specification
From 75e50549670828c4261b599b63e97abf4f43afab Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sun, 12 Dec 2021 20:03:12 -0500
Subject: [PATCH 02/31] remote-repository: Remote repository file reading
improvements for Bitbucket
---
.mvn/wrapper/maven-wrapper.properties | 2 +-
bom/pom.xml | 2 +-
cli/pom.xml | 4 +-
.../cli/BitbucketScanCommandSpec.groovy | 14 +-
.../cli/BitbucketScanSubCommandSpec.groovy | 18 +-
.../cli/GithubScanCommandSpec.groovy | 10 +-
.../flattened/sourcehawk-flattened-base.yml | 2 +-
.../sourcehawk-flattened-override.yml | 2 +-
cli/src/test/resources/sourcehawk-simple.yml | 22 --
core/pom.xml | 2 +-
.../RemoteRepositoryFileReader.java | 40 +--
.../sourcehawk/core/data/RemoteRefSpec.groovy | 28 +-
.../BitbucketRepositoryFileReaderSpec.groovy | 184 --------------
.../GithubRepositoryFileReaderSpec.groovy | 239 ------------------
.../RemoteRepositoryFileReaderSpec.groovy | 165 +++++++++---
distributions/debian/pom.xml | 2 +-
distributions/docker/pom.xml | 2 +-
distributions/linux/pom.xml | 2 +-
distributions/pom.xml | 2 +-
distributions/rpm/pom.xml | 2 +-
enforcer/core/pom.xml | 2 +-
enforcer/file/aot/pom.xml | 2 +-
enforcer/file/common/pom.xml | 2 +-
enforcer/file/core/pom.xml | 2 +-
enforcer/file/docker/pom.xml | 2 +-
enforcer/file/maven/pom.xml | 2 +-
enforcer/file/pom.xml | 2 +-
enforcer/file/registry/pom.xml | 2 +-
enforcer/pom.xml | 2 +-
exec/pom.xml | 4 +-
.../sourcehawk/exec/scan/ScanExecutor.java | 45 +++-
.../exec/scan/ScanResultFactory.java | 38 ++-
.../sourcehawk/exec/ExecOptionsSpec.groovy | 9 +-
.../resources/sourcehawk-flattened-base.yml | 2 +-
pom.xml | 2 +-
35 files changed, 255 insertions(+), 607 deletions(-)
delete mode 100644 core/src/test/groovy/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReaderSpec.groovy
delete mode 100644 core/src/test/groovy/com/optum/sourcehawk/core/repository/GithubRepositoryFileReaderSpec.groovy
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index e404372..26ae971 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1 +1 @@
-distributionUrl = https://apache.claz.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip
\ No newline at end of file
+distributionUrl = https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
\ No newline at end of file
diff --git a/bom/pom.xml b/bom/pom.xml
index 35dbd3b..c18379b 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
sourcehawk-bom
diff --git a/cli/pom.xml b/cli/pom.xml
index 441e361..aeb3dee 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -8,7 +8,7 @@
sourcehawk
com.optum.sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
sourcehawk-cli
@@ -23,7 +23,7 @@
com.optum.sourcehawk.cli.Sourcehawk
- 0.94
+ 0.91
**/picocli/**/*.*
diff --git a/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanCommandSpec.groovy b/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanCommandSpec.groovy
index 4bb99e7..249773b 100644
--- a/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanCommandSpec.groovy
+++ b/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanCommandSpec.groovy
@@ -10,11 +10,11 @@ class BitbucketScanCommandSpec extends CliBaseSpecification {
def "getRawRemoteReference"() {
when:
- Pair rawRemoteReference = new BitbucketScanCommand(bitbucket: new CommandOptions.Bitbucket(remoteReference: "owner/repo@master")).getRawRemoteReference()
+ Pair rawRemoteReference = new BitbucketScanCommand(bitbucket: new CommandOptions.Bitbucket(remoteReference: "owner/repo@master")).getRawRemoteReference()
then:
- rawRemoteReference.left == RemoteRef.Type.BITBUCKET
- rawRemoteReference.right == "owner/repo@master"
+ rawRemoteReference.left == "owner/repo@master"
+ rawRemoteReference.right == "main"
}
@Unroll
@@ -63,16 +63,16 @@ class BitbucketScanCommandSpec extends CliBaseSpecification {
def "createRepositoryFileReader"() {
given:
String rawReference = "project/repo@master"
- BitbucketScanCommand githubScanCommand = new BitbucketScanCommand(bitbucket: new CommandOptions.Bitbucket(remoteReference: "owner/repo@main"))
+ BitbucketScanCommand bitbucketScanCommand = new BitbucketScanCommand(bitbucket: new CommandOptions.Bitbucket(remoteReference: "owner/repo@main"))
when:
- RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(RemoteRef.Type.BITBUCKET, rawReference))
+ RepositoryFileReader repositoryFileReader = bitbucketScanCommand.createRepositoryFileReader(RemoteRef.parse(rawReference, "main"))
then:
repositoryFileReader
}
- def "createRepositoryFileReader - enterprise"() {
+ def "createRepositoryFileReader - server"() {
given:
String rawReference = "project/repo@master"
BitbucketScanCommand githubScanCommand = new BitbucketScanCommand(bitbucket:
@@ -80,7 +80,7 @@ class BitbucketScanCommandSpec extends CliBaseSpecification {
)
when:
- RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(RemoteRef.Type.BITBUCKET, rawReference))
+ RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(rawReference, "main"))
then:
repositoryFileReader
diff --git a/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanSubCommandSpec.groovy b/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanSubCommandSpec.groovy
index 04f639d..b17a9d7 100644
--- a/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanSubCommandSpec.groovy
+++ b/cli/src/test/groovy/com/optum/sourcehawk/cli/BitbucketScanSubCommandSpec.groovy
@@ -37,13 +37,15 @@ class BitbucketScanSubCommandSpec extends Specification {
clientAndServer
.when(HttpRequest.request()
.withMethod("HEAD")
- .withPath("/project/repo/raw/master/lombok.config"),
+ .withPath("/rest/api/1.0/projects/project/repos/repo/raw/lombok.config")
+ .withQueryStringParameter("at", "main"),
Times.exactly(1))
.respond(HttpResponse.response().withStatusCode(200))
clientAndServer
.when(HttpRequest.request()
.withMethod("GET")
- .withPath("/project/repo/raw/master/lombok.config")
+ .withPath("/rest/api/1.0/projects/project/repos/repo/raw/lombok.config")
+ .withQueryStringParameter("at", "main")
.withHeader("Accept", "text/plain"),
Times.exactly(2))
.respond(HttpResponse.response()
@@ -65,13 +67,15 @@ class BitbucketScanSubCommandSpec extends Specification {
clientAndServer
.when(HttpRequest.request()
.withMethod("HEAD")
- .withPath("/project/repo/raw/develop/lombok2.config"),
+ .withPath("/rest/api/1.0/projects/project/repos/repo/raw/lombok2.config")
+ .withQueryStringParameter("at", "main"),
Times.exactly(1))
.respond(HttpResponse.response().withStatusCode(200))
clientAndServer
.when(HttpRequest.request()
.withMethod("GET")
- .withPath("/project/repo/raw/develop/lombok2.config")
+ .withPath("/rest/api/1.0/projects/project/repos/repo/raw/lombok2.config")
+ .withQueryStringParameter("at", "main")
.withHeader("Accept", "text/plain"),
Times.exactly(2))
.respond(HttpResponse.response()
@@ -92,9 +96,9 @@ class BitbucketScanSubCommandSpec extends Specification {
String[] args = ["bitbucket", "-S", bitbucketServerUrl, "project/repo@develop" ]
clientAndServer
.when(HttpRequest.request()
- .withMethod("GET")
- .withPath("/project/repo/raw/develop/sourcehawk.yml")
- .withHeader("Accept", "text/plain"),
+ .withMethod("HEAD")
+ .withPath("/rest/api/1.0/projects/project/repos/repo/raw/lombok.config")
+ .withQueryStringParameter("at", "main"),
Times.exactly(1))
.respond(HttpResponse.notFoundResponse())
diff --git a/cli/src/test/groovy/com/optum/sourcehawk/cli/GithubScanCommandSpec.groovy b/cli/src/test/groovy/com/optum/sourcehawk/cli/GithubScanCommandSpec.groovy
index 87cfe86..6c84afe 100644
--- a/cli/src/test/groovy/com/optum/sourcehawk/cli/GithubScanCommandSpec.groovy
+++ b/cli/src/test/groovy/com/optum/sourcehawk/cli/GithubScanCommandSpec.groovy
@@ -10,11 +10,11 @@ class GithubScanCommandSpec extends CliBaseSpecification {
def "getRawRemoteReference"() {
when:
- Pair rawRemoteReference = new GithubScanCommand(github: new CommandOptions.Github(remoteReference: "owner/repo@main")).getRawRemoteReference()
+ Pair rawRemoteReference = new GithubScanCommand(github: new CommandOptions.Github(remoteReference: "owner/repo@main")).getRawRemoteReference()
then:
- rawRemoteReference.left == RemoteRef.Type.GITHUB
- rawRemoteReference.right == "owner/repo@main"
+ rawRemoteReference.left == "owner/repo@main"
+ rawRemoteReference.right == "main"
}
@Unroll
@@ -66,7 +66,7 @@ class GithubScanCommandSpec extends CliBaseSpecification {
GithubScanCommand githubScanCommand = new GithubScanCommand(github: new CommandOptions.Github(remoteReference: "owner/repo@main"))
when:
- RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(RemoteRef.Type.GITHUB, rawReference))
+ RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(rawReference, "main"))
then:
repositoryFileReader
@@ -80,7 +80,7 @@ class GithubScanCommandSpec extends CliBaseSpecification {
)
when:
- RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(RemoteRef.Type.GITHUB, rawReference))
+ RepositoryFileReader repositoryFileReader = githubScanCommand.createRepositoryFileReader(RemoteRef.parse(rawReference, "main"))
then:
repositoryFileReader
diff --git a/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml b/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
index b250224..efcca44 100644
--- a/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
+++ b/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
@@ -53,4 +53,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://apache.claz.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
diff --git a/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml b/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
index 0f6a243..8c715e9 100644
--- a/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
+++ b/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
@@ -72,4 +72,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://apache.claz.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
diff --git a/cli/src/test/resources/sourcehawk-simple.yml b/cli/src/test/resources/sourcehawk-simple.yml
index 908c760..8bf174b 100644
--- a/cli/src/test/resources/sourcehawk-simple.yml
+++ b/cli/src/test/resources/sourcehawk-simple.yml
@@ -8,28 +8,6 @@ file-protocols:
repository-path: README.md
required: true
severity: WARNING
- - name: Lombok
- repository-path: lombok.config
- required: true
- severity: WARNING
- enforcers:
- - enforcer: .common.StringPropertyEquals
- property-name: config.stopBubbling
- expected-property-value: false
- - enforcer: .common.StringPropertyEquals
- property-name: lombok.addLombokGeneratedAnnotation
- expected-property-value: false
- - name: Lombok
- repository-path: lombok.config
- required: true
- severity: WARNING
- enforcers:
- - enforcer: .common.StringPropertyEquals
- property-name: config.stopBubbling
- expected-property-value: false
- - enforcer: .common.StringPropertyEquals
- property-name: lombok.addLombokGeneratedAnnotation
- expected-property-value: false
- name: Lombok
repository-path: lombok.config
required: true
diff --git a/core/pom.xml b/core/pom.xml
index aa79050..a840223 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java b/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
index d7a5440..20c49b8 100644
--- a/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
+++ b/core/src/main/java/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReader.java
@@ -1,18 +1,15 @@
package com.optum.sourcehawk.core.repository;
-import com.optum.sourcehawk.core.utils.StringUtils;
-import lombok.NonNull;
-import lombok.val;
-
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
+import lombok.NonNull;
+import lombok.val;
/**
* A remote repository file reader which treats the repository file paths relative
@@ -48,20 +45,11 @@ public final class RemoteRepositoryFileReader implements RepositoryFileReader {
* @param rawFileUrlTemplate the raw file URL template
* @param requestProperties the request properties required for connection
*/
- public RemoteRepositoryFileReader(@NonNull final String rawFileUrlTemplate, final Map requestProperties) {
+ public RemoteRepositoryFileReader(@NonNull final String rawFileUrlTemplate, @NonNull final Map requestProperties) {
this.rawFileUrlTemplate = rawFileUrlTemplate;
this.requestProperties = requestProperties;
}
- /**
- * Constructs an instance of this reader with the provided base URL
- *
- * @param rawFileUrlTemplate the base URL
- */
- protected RemoteRepositoryFileReader(@NonNull final String rawFileUrlTemplate) {
- this(rawFileUrlTemplate, Collections.emptyMap());
- }
-
/** {@inheritDoc} */
@Override
public boolean exists(final String repositoryFilePath) throws IOException {
@@ -119,7 +107,11 @@ private boolean urlExists(final URL url) throws IOException {
val httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setRequestMethod("HEAD");
requestProperties.forEach(httpUrlConnection::setRequestProperty);
- return httpUrlConnection.getResponseCode() == HttpURLConnection.HTTP_OK;
+ val httpResponseCode = httpUrlConnection.getResponseCode();
+ if (httpResponseCode != HttpURLConnection.HTTP_OK) {
+ System.err.println("HTTP Request to " + url + " returned response code " + httpResponseCode); // FIXME
+ }
+ return httpResponseCode == HttpURLConnection.HTTP_OK;
}
/**
@@ -136,20 +128,4 @@ private static String constructAbsoluteLocation(final String rawFileUrlTemplate,
return String.format(rawFileUrlTemplate, repositoryFilePath);
}
- /**
- * Construct the request properties for the provided authorization token
- *
- * @param authorizationPrefix the authorization request property prefix
- * @param authorizationToken the authorization token
- * @return the request properties
- */
- protected static Map constructRequestProperties(final String authorizationPrefix, final String authorizationToken) {
- val requestProperties = new HashMap();
- requestProperties.put("Accept", "text/plain");
- if (StringUtils.isNotBlankOrEmpty(authorizationToken)) {
- requestProperties.put("Authorization", authorizationPrefix + authorizationToken);
- }
- return requestProperties;
- }
-
}
diff --git a/core/src/test/groovy/com/optum/sourcehawk/core/data/RemoteRefSpec.groovy b/core/src/test/groovy/com/optum/sourcehawk/core/data/RemoteRefSpec.groovy
index 5d7e567..7b26ae4 100644
--- a/core/src/test/groovy/com/optum/sourcehawk/core/data/RemoteRefSpec.groovy
+++ b/core/src/test/groovy/com/optum/sourcehawk/core/data/RemoteRefSpec.groovy
@@ -7,14 +7,12 @@ class RemoteRefSpec extends Specification {
def "builder and toString"() {
given:
- RemoteRef.Type type = RemoteRef.Type.GITHUB
String namespace = "namespace"
String repository = "repository"
String ref = "ref"
when:
RemoteRef remoteRef = RemoteRef.builder()
- .type(type)
.namespace(namespace)
.repository(repository)
.ref(ref)
@@ -22,32 +20,29 @@ class RemoteRefSpec extends Specification {
then:
remoteRef
- remoteRef.type == type
remoteRef.namespace == namespace
remoteRef.repository == repository
remoteRef.ref == ref
and:
- remoteRef.toString() == "[GITHUB] namespace/repository@ref"
+ remoteRef.toString() == "namespace/repository@ref"
}
def "parse"() {
given:
- RemoteRef.Type type = RemoteRef.Type.GITHUB
String rawReference = "namespace/repository@ref"
when:
- RemoteRef remoteRef = RemoteRef.parse(type, rawReference)
+ RemoteRef remoteRef = RemoteRef.parse(rawReference, "main")
then:
remoteRef
- remoteRef.type == type
remoteRef.namespace == "namespace"
remoteRef.repository == "repository"
remoteRef.ref == "ref"
and:
- remoteRef.toString() == "[GITHUB] ${rawReference}"
+ remoteRef.toString() == rawReference
}
@Unroll
@@ -56,31 +51,22 @@ class RemoteRefSpec extends Specification {
String rawReference = "namespace/repository"
when:
- RemoteRef remoteRef = RemoteRef.parse(type, rawReference)
+ RemoteRef remoteRef = RemoteRef.parse(rawReference, "main")
then:
remoteRef
- remoteRef.type == type
remoteRef.namespace == "namespace"
remoteRef.repository == "repository"
- remoteRef.ref == expected
+ remoteRef.ref == "main"
and:
- remoteRef.toString() == "[${type.name()}] ${rawReference}@${expected}"
-
- where:
- type | expected
- RemoteRef.Type.GITHUB | "main"
- RemoteRef.Type.BITBUCKET | "master"
+ remoteRef.toString() == "${rawReference}@main"
}
@Unroll
def "parse - invalid (throws IllegalArgumentException)"() {
- given:
- RemoteRef.Type type = RemoteRef.Type.GITHUB
-
when:
- RemoteRef.parse(type, rawReference)
+ RemoteRef.parse(rawReference, "main")
then:
thrown(IllegalArgumentException)
diff --git a/core/src/test/groovy/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReaderSpec.groovy b/core/src/test/groovy/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReaderSpec.groovy
deleted file mode 100644
index 6aef8f3..0000000
--- a/core/src/test/groovy/com/optum/sourcehawk/core/repository/BitbucketRepositoryFileReaderSpec.groovy
+++ /dev/null
@@ -1,184 +0,0 @@
-package com.optum.sourcehawk.core.repository
-
-import com.optum.sourcehawk.core.data.RemoteRef
-import org.mockserver.configuration.ConfigurationProperties
-import org.mockserver.integration.ClientAndServer
-import org.mockserver.matchers.Times
-import org.mockserver.model.HttpRequest
-import org.mockserver.model.HttpResponse
-import spock.lang.AutoCleanup
-import spock.lang.Shared
-import spock.lang.Specification
-
-class BitbucketRepositoryFileReaderSpec extends Specification {
-
- @Shared
- @AutoCleanup
- ClientAndServer clientAndServer
-
- @Shared
- String baseUrl
-
- def setupSpec() {
- clientAndServer = ClientAndServer.startClientAndServer("http://127.0.0.1", 8122)
- ConfigurationProperties.logLevel("WARN")
- baseUrl = "${clientAndServer.remoteAddress.hostString}:${clientAndServer.port}"
- }
-
- def setup() {
- clientAndServer.reset()
- }
-
- def "constructors"() {
- expect:
- new BitbucketRepositoryFileReader(null, RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master"))
- new BitbucketRepositoryFileReader("abc", "https://bitbucket.example.com/", RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master"))
- }
-
- def "supportsGlobPatterns"() {
- given:
- BitbucketRepositoryFileReader reader = new BitbucketRepositoryFileReader(null, RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master"))
-
- when:
- boolean supportsGlobPatterns = reader.supportsGlobPatterns()
-
- then:
- !supportsGlobPatterns
- }
-
- def "exists - found"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master")
- BitbucketRepositoryFileReader reader = new BitbucketRepositoryFileReader(null, baseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/project/repo/raw/master/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.response().withStatusCode(200))
-
- when:
- boolean exists = reader.exists("README.md")
-
- then:
- exists
- }
-
- def "exists - not found"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master")
- BitbucketRepositoryFileReader reader = new BitbucketRepositoryFileReader(null, baseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/project/repo/raw/master/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.notFoundResponse())
-
- when:
- boolean exists = reader.exists("README.md")
-
- then:
- !exists
- }
-
- def "read - found"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master")
- BitbucketRepositoryFileReader reader = new BitbucketRepositoryFileReader(null, baseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/project/repo/raw/master/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.response().withStatusCode(200))
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("GET")
- .withPath("/project/repo/raw/master/README.md"),
- Times.exactly(2))
- .respond(HttpResponse.response().withStatusCode(200).withBody("# Title".bytes))
-
- when:
- Optional inputStreamOptional = reader.read("README.md")
-
- then:
- inputStreamOptional
- inputStreamOptional.isPresent()
-
- when:
- inputStreamOptional = reader.read("/README.md")
-
- then:
- inputStreamOptional
- inputStreamOptional.isPresent()
- }
-
- def "read - not found"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master")
- BitbucketRepositoryFileReader reader = new BitbucketRepositoryFileReader(null, baseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/project/repo/raw/master/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.notFoundResponse())
-
- when:
- Optional inputStreamOptional = reader.read("README.md")
-
- then:
- !inputStreamOptional
- }
-
- def "constructBaseUrl"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master")
-
- when:
- String baseUrl = BitbucketRepositoryFileReader.constructBaseUrl(remoteRef, RemoteRef.Type.BITBUCKET.baseUrl)
-
- then:
- baseUrl == "https://bitbucket.org/project/repo/raw/master/"
- }
-
- def "constructor - null parameter"() {
- when:
- new BitbucketRepositoryFileReader("abc", null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new BitbucketRepositoryFileReader(null, null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new BitbucketRepositoryFileReader("abc", null, RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master"))
-
- then:
- thrown(NullPointerException)
-
- when:
- new BitbucketRepositoryFileReader(null, null, RemoteRef.parse(RemoteRef.Type.BITBUCKET, "project/repo@master"))
-
- then:
- thrown(NullPointerException)
-
- when:
- new BitbucketRepositoryFileReader("abc", null, null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new BitbucketRepositoryFileReader(null, null, null)
-
- then:
- thrown(NullPointerException)
- }
-
-}
diff --git a/core/src/test/groovy/com/optum/sourcehawk/core/repository/GithubRepositoryFileReaderSpec.groovy b/core/src/test/groovy/com/optum/sourcehawk/core/repository/GithubRepositoryFileReaderSpec.groovy
deleted file mode 100644
index d2e3e37..0000000
--- a/core/src/test/groovy/com/optum/sourcehawk/core/repository/GithubRepositoryFileReaderSpec.groovy
+++ /dev/null
@@ -1,239 +0,0 @@
-package com.optum.sourcehawk.core.repository
-
-import com.optum.sourcehawk.core.data.RemoteRef
-import org.mockserver.configuration.ConfigurationProperties
-import org.mockserver.integration.ClientAndServer
-import org.mockserver.matchers.Times
-import org.mockserver.model.HttpRequest
-import org.mockserver.model.HttpResponse
-import spock.lang.AutoCleanup
-import spock.lang.Shared
-import spock.lang.Specification
-import spock.lang.Unroll
-
-class GithubRepositoryFileReaderSpec extends Specification {
-
- @Shared
- @AutoCleanup
- ClientAndServer clientAndServer
-
- @Shared
- String enterpriseUrl
-
- def setupSpec() {
- clientAndServer = ClientAndServer.startClientAndServer("http://127.0.0.1", 8121)
- ConfigurationProperties.logLevel("WARN")
- enterpriseUrl = "${clientAndServer.remoteAddress.hostString}:${clientAndServer.port}"
- }
-
- def setup() {
- clientAndServer.reset()
- }
-
- def "supportsGlobPatterns"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
- GithubRepositoryFileReader githubRepositoryFileReader = new GithubRepositoryFileReader(null, enterpriseUrl, remoteRef)
-
- when:
- boolean supportsGlobPatterns = githubRepositoryFileReader.supportsGlobPatterns()
-
- then:
- !supportsGlobPatterns
- }
-
- def "exists (found)"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
- GithubRepositoryFileReader githubRepositoryFileReader = new GithubRepositoryFileReader(null, enterpriseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/raw/owner/repo/main/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.response().withStatusCode(200))
-
- when:
- boolean exists = githubRepositoryFileReader.exists("README.md")
-
- then:
- exists
- }
-
- def "exists (not found)"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@nope")
- GithubRepositoryFileReader githubRepositoryFileReader = new GithubRepositoryFileReader(null, enterpriseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/raw/owner/repo/main/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.notFoundResponse())
-
- when:
- boolean exists = githubRepositoryFileReader.exists("README.md")
-
- then:
- !exists
- }
-
- def "read (found)"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
- GithubRepositoryFileReader githubRepositoryFileReader = new GithubRepositoryFileReader(null, enterpriseUrl, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/raw/owner/repo/main/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.response().withStatusCode(200))
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("GET")
- .withPath("/raw/owner/repo/main/README.md"),
- Times.exactly(2))
- .respond(HttpResponse.response().withStatusCode(200).withBody("# Title".bytes))
-
- when:
- Optional inputStream = githubRepositoryFileReader.read("README.md")
-
- then:
- inputStream
- inputStream.isPresent()
-
- when:
- inputStream = githubRepositoryFileReader.read("/README.md")
-
- then:
- inputStream
- inputStream.isPresent()
- }
-
- def "read (not found)"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@master")
- GithubRepositoryFileReader githubRepositoryFileReader = new GithubRepositoryFileReader(null, remoteRef)
- clientAndServer
- .when(HttpRequest.request()
- .withMethod("HEAD")
- .withPath("/raw/owner/repo/master/README.md"),
- Times.exactly(1))
- .respond(HttpResponse.notFoundResponse())
-
- when:
- Optional inputStream = githubRepositoryFileReader.read("README.md")
-
- then:
- !inputStream
- !inputStream.isPresent()
- }
-
- def "constructBaseUrl - public github"() {
- given:
- String githubUrl = "https://raw.githubusercontent.com"
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
-
- when:
- String baseUrl = GithubRepositoryFileReader.constructBaseUrl(githubUrl, false, remoteRef)
-
- then:
- baseUrl == "https://raw.githubusercontent.com/owner/repo/main/"
- }
-
- @Unroll
- def "constructBaseUrl - enterprise github"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
-
- when:
- String baseUrl = GithubRepositoryFileReader.constructBaseUrl(githubUrl, true, remoteRef)
-
- then:
- baseUrl == "https://github.example.com/raw/owner/repo/main/"
-
- where:
- githubUrl << ["https://github.example.com", "https://github.example.com/"]
- }
-
- def "constructRequestProperties"() {
- when:
- Map requestProperties = GithubRepositoryFileReader.constructRequestProperties("token ", "abc")
-
- then:
- requestProperties
- requestProperties.size() == 2
- requestProperties["Accept"] == "text/plain"
- requestProperties["Authorization"] == "token abc"
- }
-
- def "constructRequestProperties - null"() {
- when:
- Map requestProperties = GithubRepositoryFileReader.constructRequestProperties("token ", null)
-
- then:
- requestProperties
- requestProperties.size() == 1
- requestProperties["Accept"] == "text/plain"
- }
-
- def "constructor - enterprise"() {
- given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
-
- expect:
- new GithubRepositoryFileReader(null, "https://github.example.com", remoteRef)
- new GithubRepositoryFileReader("abc", "https://github.example.com", remoteRef)
- }
-
- def "constructors - null parameter"() {
- when:
- new GithubRepositoryFileReader(null, null, null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader("abc", null, null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader("abc", null, RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main"))
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader("abc", "https://github.example.com", null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader(null, "https://github.example.com", null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader(null, null, RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main"))
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader("abc", null)
-
- then:
- thrown(NullPointerException)
-
- when:
- new GithubRepositoryFileReader(null, null)
-
- then:
- thrown(NullPointerException)
- }
-
-}
diff --git a/core/src/test/groovy/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReaderSpec.groovy b/core/src/test/groovy/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReaderSpec.groovy
index 51592b5..ef755dc 100644
--- a/core/src/test/groovy/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReaderSpec.groovy
+++ b/core/src/test/groovy/com/optum/sourcehawk/core/repository/RemoteRepositoryFileReaderSpec.groovy
@@ -1,71 +1,168 @@
package com.optum.sourcehawk.core.repository
-import spock.lang.Specification
+import org.mockserver.configuration.ConfigurationProperties
+import org.mockserver.integration.ClientAndServer
+import org.mockserver.matchers.Times
+import org.mockserver.model.HttpRequest
+import org.mockserver.model.HttpResponse
+import spock.lang.AutoCleanup
+import spock.lang.Shared
+import spock.lang.Specification
class RemoteRepositoryFileReaderSpec extends Specification {
- def "constructor"() {
- expect:
- new GenericRemoteRepositoryFileReader()
- new TrailingSlashRemoteRepositoryFileReader()
+ @Shared
+ @AutoCleanup
+ ClientAndServer clientAndServer
+
+ @Shared
+ String baseUrl
+
+ def setupSpec() {
+ clientAndServer = ClientAndServer.startClientAndServer("http://127.0.0.1", 8122)
+ ConfigurationProperties.logLevel("WARN")
+ baseUrl = "${clientAndServer.remoteAddress.hostString}:${clientAndServer.port}"
}
- def "constructor - null argument"() {
+ def "supportsGlobPatterns"() {
+ given:
+ RepositoryFileReader reader = new RemoteRepositoryFileReader("rawFileUrlTemplate", Collections.emptyMap())
+
when:
- new InvalidRemoteRepositoryFileReader()
+ boolean supportsGlobPatterns = reader.supportsGlobPatterns()
then:
- thrown(NullPointerException)
+ !supportsGlobPatterns
+ }
+
+ def "exists - found"() {
+ given:
+ String rawFileUrlTemplate = "$baseUrl/project/repo/raw/master/%s"
+ RepositoryFileReader reader = new RemoteRepositoryFileReader(rawFileUrlTemplate, Collections.emptyMap())
+ clientAndServer
+ .when(HttpRequest.request()
+ .withMethod("HEAD")
+ .withPath("/project/repo/raw/master/README.md"),
+ Times.exactly(1))
+ .respond(HttpResponse.response().withStatusCode(200))
when:
- new InvalidRemoteRepositoryFileReader2()
+ boolean exists = reader.exists("README.md")
then:
- thrown(NullPointerException)
+ exists
}
- def "getInputStream - not found"() {
+ def "exists - not found"() {
given:
- HttpURLConnection mockHttpUrlConnection = Mock()
+ String rawFileUrlTemplate = "$baseUrl/project/repo/raw/master/%s"
+ RepositoryFileReader reader = new RemoteRepositoryFileReader(rawFileUrlTemplate, Collections.emptyMap())
+ clientAndServer
+ .when(HttpRequest.request()
+ .withMethod("HEAD")
+ .withPath("/project/repo/raw/master/README.md"),
+ Times.exactly(1))
+ .respond(HttpResponse.notFoundResponse())
when:
- Optional inputStreamOptional = RemoteRepositoryFileReader.getInputStream(mockHttpUrlConnection)
+ boolean exists = reader.exists("README.md")
then:
- 1 * mockHttpUrlConnection.getInputStream() >> { throw new FileNotFoundException("404") }
- 0 * _
-
- and:
- !inputStreamOptional.isPresent()
+ !exists
}
- private static class GenericRemoteRepositoryFileReader extends RemoteRepositoryFileReader {
+ def "read - found"() {
+ given:
+ String rawFileUrlTemplate = "$baseUrl/raw/project/repo/main/%s"
+ RepositoryFileReader reader = new RemoteRepositoryFileReader(rawFileUrlTemplate, Collections.emptyMap())
+ clientAndServer
+ .when(HttpRequest.request()
+ .withMethod("HEAD")
+ .withPath("/raw/project/repo/main/README.md"),
+ Times.exactly(1))
+ .respond(HttpResponse.response().withStatusCode(200))
+ clientAndServer
+ .when(HttpRequest.request()
+ .withMethod("GET")
+ .withPath("/raw/project/repo/main/README.md"),
+ Times.exactly(2))
+ .respond(HttpResponse.response().withStatusCode(200).withBody("# Title".bytes))
+
+ when:
+ Optional inputStreamOptional = reader.read("README.md")
+
+ then:
+ inputStreamOptional
+ inputStreamOptional.isPresent()
+
+ when:
+ inputStreamOptional = reader.read("/README.md")
- protected GenericRemoteRepositoryFileReader() {
- super("https://optum.github.io")
- }
+ then:
+ inputStreamOptional
+ inputStreamOptional.isPresent()
}
- private static class TrailingSlashRemoteRepositoryFileReader extends RemoteRepositoryFileReader {
+ def "read - not found"() {
+ given:
+ String rawFileUrlTemplate = "$baseUrl/raw/project/repo/main/%s"
+ RepositoryFileReader reader = new RemoteRepositoryFileReader(rawFileUrlTemplate, Collections.emptyMap())
+ clientAndServer
+ .when(HttpRequest.request()
+ .withMethod("HEAD")
+ .withPath("/raw/project/repo/main/README.md"),
+ Times.exactly(1))
+ .respond(HttpResponse.notFoundResponse())
+
+ when:
+ Optional inputStreamOptional = reader.read("README.md")
- protected TrailingSlashRemoteRepositoryFileReader() {
- super("https://optum.github.io/")
- }
+ then:
+ !inputStreamOptional.isPresent()
}
- private static class InvalidRemoteRepositoryFileReader extends RemoteRepositoryFileReader {
+ def "getAbsoluteLocation"() {
+ given:
+ String rawFileUrlTemplate = "$baseUrl/raw/project/repo/main/%s"
+ RepositoryFileReader reader = new RemoteRepositoryFileReader(rawFileUrlTemplate, Collections.emptyMap())
+ String repositoryFilePath = "README.md"
+
+ when:
+ String absoluteLocation = reader.getAbsoluteLocation(repositoryFilePath)
+
+ then:
+ absoluteLocation
+ absoluteLocation == "$baseUrl/raw/project/repo/main/README.md"
+
+
+ when:
+ repositoryFilePath = "/path/to/file.txt"
+ absoluteLocation = reader.getAbsoluteLocation(repositoryFilePath)
- protected InvalidRemoteRepositoryFileReader() {
- super(null)
- }
+ then:
+ absoluteLocation
+ absoluteLocation == "$baseUrl/raw/project/repo/main/path/to/file.txt"
}
- private static class InvalidRemoteRepositoryFileReader2 extends RemoteRepositoryFileReader {
+ def "constructor - null parameter"() {
+ when:
+ new RemoteRepositoryFileReader("abc", null)
+
+ then:
+ thrown(NullPointerException)
+
+ when:
+ new RemoteRepositoryFileReader(null, Collections.emptyMap())
+
+ then:
+ thrown(NullPointerException)
+
+ when:
+ new RemoteRepositoryFileReader(null, null)
- protected InvalidRemoteRepositoryFileReader2() {
- super(null, Collections.emptyMap())
- }
+ then:
+ thrown(NullPointerException)
}
}
\ No newline at end of file
diff --git a/distributions/debian/pom.xml b/distributions/debian/pom.xml
index 7c27965..359aeec 100644
--- a/distributions/debian/pom.xml
+++ b/distributions/debian/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/distributions/docker/pom.xml b/distributions/docker/pom.xml
index 4412275..bb59e6f 100644
--- a/distributions/docker/pom.xml
+++ b/distributions/docker/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 561a2ca..be5e6dc 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/distributions/pom.xml b/distributions/pom.xml
index a5e8fb1..e1a410e 100644
--- a/distributions/pom.xml
+++ b/distributions/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/distributions/rpm/pom.xml b/distributions/rpm/pom.xml
index 4a63270..10bac32 100644
--- a/distributions/rpm/pom.xml
+++ b/distributions/rpm/pom.xml
@@ -8,7 +8,7 @@
sourcehawk-dist
com.optum.sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
sourcehawk-dist-rpm
diff --git a/enforcer/core/pom.xml b/enforcer/core/pom.xml
index 11ef76f..93e09a2 100644
--- a/enforcer/core/pom.xml
+++ b/enforcer/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/aot/pom.xml b/enforcer/file/aot/pom.xml
index 28d027c..7c233bf 100644
--- a/enforcer/file/aot/pom.xml
+++ b/enforcer/file/aot/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/common/pom.xml b/enforcer/file/common/pom.xml
index aab36b7..8d0ef8a 100644
--- a/enforcer/file/common/pom.xml
+++ b/enforcer/file/common/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/core/pom.xml b/enforcer/file/core/pom.xml
index 082fa20..cd74cb7 100644
--- a/enforcer/file/core/pom.xml
+++ b/enforcer/file/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/docker/pom.xml b/enforcer/file/docker/pom.xml
index bda2632..988a7bc 100644
--- a/enforcer/file/docker/pom.xml
+++ b/enforcer/file/docker/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/maven/pom.xml b/enforcer/file/maven/pom.xml
index 06e1453..fba5aea 100644
--- a/enforcer/file/maven/pom.xml
+++ b/enforcer/file/maven/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/pom.xml b/enforcer/file/pom.xml
index 5ef024b..1852619 100644
--- a/enforcer/file/pom.xml
+++ b/enforcer/file/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/registry/pom.xml b/enforcer/file/registry/pom.xml
index 71ac145..bf8c359 100644
--- a/enforcer/file/registry/pom.xml
+++ b/enforcer/file/registry/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/enforcer/pom.xml b/enforcer/pom.xml
index 2ecf225..6254ec3 100644
--- a/enforcer/pom.xml
+++ b/enforcer/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
diff --git a/exec/pom.xml b/exec/pom.xml
index a517011..1033150 100644
--- a/exec/pom.xml
+++ b/exec/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
../pom.xml
@@ -19,7 +19,7 @@
- 0.88
+ 0.87
diff --git a/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanExecutor.java b/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanExecutor.java
index edfbdce..7c8e96f 100644
--- a/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanExecutor.java
+++ b/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanExecutor.java
@@ -1,19 +1,15 @@
package com.optum.sourcehawk.exec.scan;
import com.optum.sourcehawk.core.configuration.SourcehawkConfiguration;
+import com.optum.sourcehawk.core.data.Severity;
import com.optum.sourcehawk.core.protocol.file.FileProtocol;
import com.optum.sourcehawk.core.result.ScanResult;
-import com.optum.sourcehawk.core.data.Severity;
import com.optum.sourcehawk.core.utils.CollectionUtils;
import com.optum.sourcehawk.core.utils.FileUtils;
import com.optum.sourcehawk.core.utils.Try;
import com.optum.sourcehawk.enforcer.file.FileEnforcer;
import com.optum.sourcehawk.exec.ConfigurationReader;
import com.optum.sourcehawk.exec.ExecOptions;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.val;
-
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -21,6 +17,9 @@
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.val;
/**
* Entry point into executing scans
@@ -117,7 +116,11 @@ private static ScanResult enforceFileProtocol(final ExecOptions execOptions, fin
if (execOptions.getRepositoryFileReader().supportsGlobPatterns() && FileUtils.isGlobPattern(fileProtocol.getRepositoryPath())) {
fileProtocolScanResults.addAll(executeFileEnforcerOnGlob(execOptions, fileProtocol, fileEnforcer));
} else {
- fileProtocolScanResults.add(executeFileEnforcer(execOptions, fileProtocol.getRepositoryPath(), fileProtocol.getSeverity(), fileEnforcer));
+ val scanResult = executeFileEnforcer(execOptions, fileProtocol.getRepositoryPath(), fileProtocol, fileEnforcer);
+ fileProtocolScanResults.add(scanResult);
+ if (isScanResultFileNotFound(scanResult)) {
+ break;
+ }
}
}
return fileProtocolScanResults.stream()
@@ -145,7 +148,7 @@ private static Collection executeFileEnforcerOnGlob(final ExecOption
}
val fileEnforcerScanResults = new ArrayList(repositoryPaths.size());
for (val repositoryPath : repositoryPaths) {
- fileEnforcerScanResults.add(executeFileEnforcer(execOptions, repositoryPath, fileProtocol.getSeverity(), fileEnforcer));
+ fileEnforcerScanResults.add(executeFileEnforcer(execOptions, repositoryPath, fileProtocol, fileEnforcer));
}
return fileEnforcerScanResults;
}
@@ -154,19 +157,33 @@ private static Collection executeFileEnforcerOnGlob(final ExecOption
* Execute the file enforcer to produce the scan result
*
* @param execOptions the exec options
- * @param repositoryFilePath the repository file path
- * @param severity the severity of the file protocol
+ * @param repositoryPath the repository path
+ * @param fileProtocol the file protocol
* @param fileEnforcer the file enforcer to execute
* @return the scan result
* @throws IOException if any error occurs accessing the file or executing enforcer
*/
- private static ScanResult executeFileEnforcer(final ExecOptions execOptions, final String repositoryFilePath, final String severity,
- final FileEnforcer fileEnforcer) throws IOException {
- try (val fileInputStream = execOptions.getRepositoryFileReader().read(repositoryFilePath)
- .orElseThrow(() -> new IOException(String.format("File not found: %s", repositoryFilePath)))) {
+ private static ScanResult executeFileEnforcer(final ExecOptions execOptions, final String repositoryPath, final FileProtocol fileProtocol,
+ final FileEnforcer fileEnforcer) throws IOException {
+ val fileInputStreamOptional = execOptions.getRepositoryFileReader().read(repositoryPath);
+ if (!fileInputStreamOptional.isPresent()) {
+ return ScanResultFactory.fileNotFound(execOptions, repositoryPath, fileProtocol.getSeverity());
+ }
+ try (val fileInputStream = fileInputStreamOptional.get()) {
val enforcerResult = fileEnforcer.enforce(fileInputStream);
- return ScanResultFactory.enforcerResult(execOptions, repositoryFilePath, Severity.parse(severity), enforcerResult);
+ return ScanResultFactory.enforcerResult(execOptions, repositoryPath, Severity.parse(fileProtocol.getSeverity()), enforcerResult);
}
}
+ /**
+ * Determine if the {@link ScanResult} is because the file was not found
+ *
+ * @param scanResult the scan result
+ * @return true if because of file not being found, false otherwise
+ */
+ private static boolean isScanResultFileNotFound(final ScanResult scanResult) {
+ return scanResult.getFormattedMessages().size() == 1
+ && scanResult.getFormattedMessages().stream().anyMatch(message -> message.contains("File not found"));
+ }
+
}
diff --git a/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanResultFactory.java b/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanResultFactory.java
index 32c3245..9bf3099 100644
--- a/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanResultFactory.java
+++ b/exec/src/main/java/com/optum/sourcehawk/exec/scan/ScanResultFactory.java
@@ -5,13 +5,12 @@
import com.optum.sourcehawk.core.result.ScanResult;
import com.optum.sourcehawk.enforcer.EnforcerResult;
import com.optum.sourcehawk.exec.ExecOptions;
-import lombok.experimental.UtilityClass;
-import lombok.val;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Optional;
import java.util.function.IntConsumer;
+import lombok.experimental.UtilityClass;
+import lombok.val;
/**
* A factory for creating instances of {@link ScanResult}
@@ -95,18 +94,31 @@ public ScanResult globalError(final Throwable throwable) {
* @return the file not found scan result
*/
public ScanResult fileNotFound(final ExecOptions execOptions, final FileProtocol fileProtocol) {
- val severity = Severity.parse(fileProtocol.getSeverity());
+ return fileNotFound(execOptions, fileProtocol.getRepositoryPath(), fileProtocol.getSeverity());
+ }
+
+ /**
+ * Generate a scan result for situations where the file is not found
+ *
+ * @param execOptions the exec options
+ * @param repositoryPath the repository path
+ * @param fileProtocolSeverity the file protocol severity
+ * @return the file not found scan result
+ */
+ public ScanResult fileNotFound(final ExecOptions execOptions, final String repositoryPath, final String fileProtocolSeverity) {
+ val severity = Severity.parse(fileProtocolSeverity);
val messageDescriptor = ScanResult.MessageDescriptor.builder()
- .severity(fileProtocol.getSeverity())
- .repositoryPath(fileProtocol.getRepositoryPath())
- .message("File not found")
- .build();
+ .severity(fileProtocolSeverity)
+ .repositoryPath(repositoryPath)
+ .message("File not found")
+ .build();
val scanResultBuilder = ScanResult.builder()
- .passed(Severity.WARNING.equals(severity) && !execOptions.isFailOnWarnings())
- .messages(Collections.singletonMap(fileProtocol.getRepositoryPath(), Collections.singleton(messageDescriptor)))
- .formattedMessages(Collections.singleton(messageDescriptor.toString()));
- return acceptCount(scanResultBuilder, Severity.parse(fileProtocol.getSeverity()), 1)
- .build();
+
+ .passed(Severity.WARNING.equals(severity) && !execOptions.isFailOnWarnings())
+ .messages(Collections.singletonMap(repositoryPath, Collections.singleton(messageDescriptor)))
+ .formattedMessages(Collections.singleton(messageDescriptor.toString()));
+ return acceptCount(scanResultBuilder, severity, 1)
+ .build();
}
/**
diff --git a/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy b/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
index 91bd09a..20adfc2 100644
--- a/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
+++ b/exec/src/test/groovy/com/optum/sourcehawk/exec/ExecOptionsSpec.groovy
@@ -4,6 +4,7 @@ import com.optum.sourcehawk.core.data.RemoteRef
import com.optum.sourcehawk.core.repository.LocalRepositoryFileReader
import com.optum.sourcehawk.core.data.Verbosity
+import com.optum.sourcehawk.core.repository.RemoteRepositoryFileReader
import spock.lang.Specification
import java.nio.file.Paths
@@ -54,15 +55,15 @@ class ExecOptionsSpec extends Specification {
!execOptions.remoteRef
}
- def "builder - github"() {
+ def "builder - remote"() {
given:
- RemoteRef remoteRef = RemoteRef.parse(RemoteRef.Type.GITHUB, "owner/repo@main")
+ RemoteRef remoteRef = RemoteRef.parse("owner/repo", "main")
ExecOptions.ExecOptionsBuilder builder = ExecOptions.builder()
.repositoryRoot(Paths.get("/"))
.configurationFileLocation("Sourcehawk")
.verbosity(Verbosity.ZERO)
.failOnWarnings(true)
- .repositoryFileReader(new GithubRepositoryFileReader("token", remoteRef))
+ .repositoryFileReader(new RemoteRepositoryFileReader("https://raw.githubusercontent.com/owner/repo/main/%s", Collections.emptyMap()))
.remoteRef(remoteRef)
when:
@@ -75,7 +76,7 @@ class ExecOptionsSpec extends Specification {
execOptions.verbosity == Verbosity.ZERO
!execOptions.tags
execOptions.failOnWarnings
- execOptions.repositoryFileReader instanceof GithubRepositoryFileReader
+ execOptions.repositoryFileReader instanceof RemoteRepositoryFileReader
execOptions.remoteRef == remoteRef
}
diff --git a/exec/src/test/resources/sourcehawk-flattened-base.yml b/exec/src/test/resources/sourcehawk-flattened-base.yml
index b250224..efcca44 100644
--- a/exec/src/test/resources/sourcehawk-flattened-base.yml
+++ b/exec/src/test/resources/sourcehawk-flattened-base.yml
@@ -53,4 +53,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://apache.claz.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
diff --git a/pom.xml b/pom.xml
index 8ecf522..c19b514 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
sourcehawk
- 0.6.0-SNAPSHOT
+ 0.6.1-SNAPSHOT
pom
Sourcehawk
From 74635f5b7d78d8901f422a329bfa47e4d4322649 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 14:43:31 -0500
Subject: [PATCH 03/31] remote-repository: Fix maven version
---
.mvn/wrapper/maven-wrapper.properties | 2 +-
cli/src/test/resources/flattened/sourcehawk-flattened-base.yml | 2 +-
exec/src/test/resources/sourcehawk-flattened-base.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index 26ae971..f8b5614 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1 +1 @@
-distributionUrl = https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
\ No newline at end of file
+distributionUrl = https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
\ No newline at end of file
diff --git a/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml b/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
index efcca44..2a183f9 100644
--- a/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
+++ b/cli/src/test/resources/flattened/sourcehawk-flattened-base.yml
@@ -53,4 +53,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip"
diff --git a/exec/src/test/resources/sourcehawk-flattened-base.yml b/exec/src/test/resources/sourcehawk-flattened-base.yml
index efcca44..2a183f9 100644
--- a/exec/src/test/resources/sourcehawk-flattened-base.yml
+++ b/exec/src/test/resources/sourcehawk-flattened-base.yml
@@ -53,4 +53,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip"
From ac60c9321010c71c67735206f305255566a3ceec Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 18:47:36 -0500
Subject: [PATCH 04/31] remote-repository: Update groovy to 3.0.9 for JDK 17
support
---
attribution.txt | 4 ++--
pom.xml | 8 +++++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/attribution.txt b/attribution.txt
index e9b35ea..e3879aa 100644
--- a/attribution.txt
+++ b/attribution.txt
@@ -390,7 +390,7 @@ https://opensource.org/licenses/BSD-2-Clause
-------------------------------------------------------------------------------------------------------------------------------
-Package: org.spockframework:spock-core:2.0-M3-groovy-3.0
+Package: org.spockframework:spock-core:2.0-groovy-3.0
License: Apache-2.0
@@ -1847,7 +1847,7 @@ limitations under the License.
-------------------------------------------------------------------------------------------------------------------------------
-Package: org.codehaus.groovy:groovy:3.0.4
+Package: org.codehaus.groovy:groovy:3.0.9
License: Apache-2.0
diff --git a/pom.xml b/pom.xml
index c19b514..de5374f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,13 @@
org.spockframework
spock-core
- 2.0-M3-groovy-3.0
+ 2.0-groovy-3.0
+ test
+
+
+ org.codehaus.groovy
+ groovy
+ ${groovy.version}
test
From 546c03a7a120d38833b21514ec7f47429e27e071 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 18:55:04 -0500
Subject: [PATCH 05/31] remote-repository: Fix maven version in test
---
.../resources/flattened/sourcehawk-flattened-override.yml | 2 +-
pom.xml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml b/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
index 8c715e9..865aeb5 100644
--- a/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
+++ b/cli/src/test/resources/flattened/sourcehawk-flattened-override.yml
@@ -72,4 +72,4 @@ file-protocols:
enforcers:
- enforcer: ".common.StringPropertyEquals"
property-name: "distributionUrl"
- expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip"
+ expected-property-value: "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip"
diff --git a/pom.xml b/pom.xml
index de5374f..ab8b605 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
0.97
- 1.7.30
+ 1.7.32
e1
@@ -120,7 +120,7 @@
junit
junit
- 4.13.1
+ 4.13.2
test
From d80fc0539bf21c3971a2e687e7fce97bbb9391b9 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 19:17:46 -0500
Subject: [PATCH 06/31] remote-repository: Fix more tests for JDK 17
---
.../com/optum/sourcehawk/cli/CliBaseSpecification.groovy | 2 +-
.../aot/SourcehawkFileEnforcerRegistryProcessorSpec.groovy | 4 +++-
.../com/optum/sourcehawk/exec/ConfigurationReaderSpec.groovy | 5 ++---
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/cli/src/test/groovy/com/optum/sourcehawk/cli/CliBaseSpecification.groovy b/cli/src/test/groovy/com/optum/sourcehawk/cli/CliBaseSpecification.groovy
index fafc98c..690f599 100644
--- a/cli/src/test/groovy/com/optum/sourcehawk/cli/CliBaseSpecification.groovy
+++ b/cli/src/test/groovy/com/optum/sourcehawk/cli/CliBaseSpecification.groovy
@@ -31,7 +31,7 @@ class CliBaseSpecification extends Specification {
}
def cleanupSpec() {
- System.setSecurityManager(defaultSecurityManager)
+ System.setSecurityManager(defaultSecurityManager) // TODO: Deprecated starting in JDK 17
}
protected void createParentDirectories(final File child) {
diff --git a/enforcer/file/aot/src/test/groovy/com/optum/sourcehawk/enforcer/file/aot/SourcehawkFileEnforcerRegistryProcessorSpec.groovy b/enforcer/file/aot/src/test/groovy/com/optum/sourcehawk/enforcer/file/aot/SourcehawkFileEnforcerRegistryProcessorSpec.groovy
index 1aa5c6f..d657afd 100644
--- a/enforcer/file/aot/src/test/groovy/com/optum/sourcehawk/enforcer/file/aot/SourcehawkFileEnforcerRegistryProcessorSpec.groovy
+++ b/enforcer/file/aot/src/test/groovy/com/optum/sourcehawk/enforcer/file/aot/SourcehawkFileEnforcerRegistryProcessorSpec.groovy
@@ -154,7 +154,9 @@ class SourcehawkFileEnforcerRegistryProcessorSpec extends Specification {
1 * mockProcessingEnvironment.getFiler() >> mockFiler
1 * mockFiler.createSourceFile("com.optum.sourcehawk.enforcer.file.FileEnforcerRegistry", []) >> null
1 * mockProcessingEnvironment.getMessager() >> mockMessager
- 1 * mockMessager.printMessage(Diagnostic.Kind.ERROR, 'Unable to generate file enforcer registry: java.lang.NullPointerException')
+ 1 * mockMessager.printMessage(Diagnostic.Kind.ERROR, _ as String) >> { kind, msg ->
+ msg == 'Unable to generate file enforcer registry: java.lang.NullPointerException'
+ }
0 * _
and:
diff --git a/exec/src/test/groovy/com/optum/sourcehawk/exec/ConfigurationReaderSpec.groovy b/exec/src/test/groovy/com/optum/sourcehawk/exec/ConfigurationReaderSpec.groovy
index d4ee1fe..ba6c9cf 100644
--- a/exec/src/test/groovy/com/optum/sourcehawk/exec/ConfigurationReaderSpec.groovy
+++ b/exec/src/test/groovy/com/optum/sourcehawk/exec/ConfigurationReaderSpec.groovy
@@ -2,7 +2,6 @@ package com.optum.sourcehawk.exec
import com.optum.sourcehawk.core.configuration.SourcehawkConfiguration
import org.spockframework.util.IoUtil
-import sun.nio.ch.ChannelInputStream
class ConfigurationReaderSpec extends FileBaseSpecification {
@@ -38,7 +37,7 @@ class ConfigurationReaderSpec extends FileBaseSpecification {
InputStream inputStream = ConfigurationReader.obtainInputStream(repositoryRoot, configurationFileLocation).get()
then:
- inputStream instanceof ChannelInputStream
+ inputStream.class.name == 'sun.nio.ch.ChannelInputStream'
}
def "obtainInputStream - relative file"() {
@@ -50,7 +49,7 @@ class ConfigurationReaderSpec extends FileBaseSpecification {
then:
inputStream
- inputStream instanceof ChannelInputStream
+ inputStream.class.name == 'sun.nio.ch.ChannelInputStream'
}
def "merge"() {
From 2068edaf2979d1555518ae8ad0cb61ae14bc4d7a Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 19:27:25 -0500
Subject: [PATCH 07/31] remote-repository: Fix Dockerfile ci images references
---
distributions/linux/native-image-builder/Dockerfile | 2 +-
distributions/rpm/Dockerfile | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/distributions/linux/native-image-builder/Dockerfile b/distributions/linux/native-image-builder/Dockerfile
index ce6898d..c2cda94 100644
--- a/distributions/linux/native-image-builder/Dockerfile
+++ b/distributions/linux/native-image-builder/Dockerfile
@@ -1,5 +1,5 @@
ARG GRAALVM_VERSION=21.3.0-java8
-FROM ghcr.io/optum/sourcehawk-ci/nativeimage:graalvm-ce-${GRAALVM_VERSION}
+FROM ghcr.io/optum/ci/nativeimage:graalvm-ce-${GRAALVM_VERSION}
# Build Arguments
ARG NAME
diff --git a/distributions/rpm/Dockerfile b/distributions/rpm/Dockerfile
index 7b8d31a..430d963 100644
--- a/distributions/rpm/Dockerfile
+++ b/distributions/rpm/Dockerfile
@@ -1,5 +1,5 @@
ARG FROM_TAG=centos7
-FROM ghcr.io/optum/sourcehawk-ci/rpmbuild:${FROM_TAG}
+FROM ghcr.io/optum/ci/rpmbuild:${FROM_TAG}
# Build Arguments
ARG RPM_BUILD_DIRECTORY
From cc2fa222dd433be73948e274cf63f3ff15adc1b3 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 19:32:10 -0500
Subject: [PATCH 08/31] remote-repository: Fix java8 graalvm version
---
distributions/linux/native-image-builder/Dockerfile | 2 +-
distributions/linux/pom.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/distributions/linux/native-image-builder/Dockerfile b/distributions/linux/native-image-builder/Dockerfile
index c2cda94..2551249 100644
--- a/distributions/linux/native-image-builder/Dockerfile
+++ b/distributions/linux/native-image-builder/Dockerfile
@@ -1,4 +1,4 @@
-ARG GRAALVM_VERSION=21.3.0-java8
+ARG GRAALVM_VERSION=21.2.0-java8
FROM ghcr.io/optum/ci/nativeimage:graalvm-ce-${GRAALVM_VERSION}
# Build Arguments
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index be5e6dc..610b8ea 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -236,7 +236,7 @@
8
- 21.3.0-java8
+ 21.2.0-java8
From 7ddac548fcd4fed923e94340cc54490e2d29edc8 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 20:09:27 -0500
Subject: [PATCH 09/31] remote-repository: Vulnerability fixes, Fixes #38,
Fixes #59, update ci with docker login and graalvm github actions
---
.github/workflows/maven-ci.yml | 35 ++++++++++++++++++----------------
.github/workflows/release.yml | 35 ++++++++++++++++++----------------
attribution.txt | 2 +-
enforcer/file/maven/pom.xml | 2 +-
4 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index aae2c26..c70b4f6 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -61,6 +61,12 @@ jobs:
server-password: SONATYPE_PASSWORD
gpg-private-key: ${{ secrets.SONATYPE_GPG_PRIVATE_KEY }}
gpg-passphrase: SONATYPE_GPG_PASSPHRASE
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v1
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
- name: Set Maven Project Version
shell: bash
run: |
@@ -138,11 +144,12 @@ jobs:
with:
java-version: 8
- name: Setup GraalVM
- uses: DeLaGuardo/setup-graalvm@master
+ uses: graalvm/setup-graalvm@v1
with:
- graalvm-version: 21.2.0.java8
- - name: Setup GraalVM Native Image Tool
- run: gu install native-image
+ version: '21.2.0'
+ java-version: '8'
+ components: 'native-image'
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Mac Native Image
if: success()
working-directory: build
@@ -180,20 +187,16 @@ jobs:
- name: Rename Native Image JAR
working-directory: build
run: ren *.jar native-image.jar
- - name: Setup GraalVM Native Image and Visual C Build Tools
- run: |
- Invoke-RestMethod -Uri https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-windows-amd64-21.3.0.zip -OutFile 'graal.zip'
- Expand-Archive -path 'graal.zip' -destinationpath '.'
- graalvm-ce-java11-21.3.0\bin\gu.cmd install native-image
- choco install visualstudio2017-workload-vctools
+ - name: Setup GraalVM
+ uses: graalvm/setup-graalvm@v1
+ with:
+ version: '21.3.0'
+ java-version: '11'
+ components: 'native-image'
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Windows Native Image
if: success()
- shell: cmd
- run: |
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
- graalvm-ce-java11-21.3.0\bin\native-image -cp .\build\native-image.jar -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime
- env:
- JAVA_HOME: ./graalvm-ce-java11-21.3.0
+ run: native-image.cmd -cp .\build\native-image.jar -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime
- name: Archive Windows Native Image
if: success()
continue-on-error: true
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 519f563..2cea482 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -37,6 +37,12 @@ jobs:
server-password: SONATYPE_PASSWORD
gpg-private-key: ${{ secrets.SONATYPE_GPG_PRIVATE_KEY }}
gpg-passphrase: SONATYPE_GPG_PASSPHRASE
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v1
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
- name: Set Maven Project Version
id: set_maven_project_version
shell: bash
@@ -226,11 +232,12 @@ jobs:
with:
java-version: 8
- name: Setup GraalVM
- uses: DeLaGuardo/setup-graalvm@master
+ uses: graalvm/setup-graalvm@v1
with:
- graalvm-version: 21.2.0.java8
- - name: Setup GraalVM Native Image Tool
- run: gu install native-image
+ version: '21.2.0'
+ java-version: '8'
+ components: 'native-image'
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Mac Native Image
if: success()
working-directory: build
@@ -289,20 +296,16 @@ jobs:
- name: Rename Native Image JAR
working-directory: build
run: ren *.jar native-image.jar
- - name: Setup GraalVM Native Image and Visual C Build Tools
- run: |
- Invoke-RestMethod -Uri https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/graalvm-ce-java11-windows-amd64-21.3.0.zip -OutFile 'graal.zip'
- Expand-Archive -path 'graal.zip' -destinationpath '.'
- graalvm-ce-java11-21.3.0\bin\gu.cmd install native-image
- choco install visualstudio2017-workload-vctools
+ - name: Setup GraalVM
+ uses: graalvm/setup-graalvm@v1
+ with:
+ version: '21.3.0'
+ java-version: '11'
+ components: 'native-image'
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Windows Native Image
if: success()
- shell: cmd
- run: |
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
- graalvm-ce-java11-21.3.0\bin\native-image -cp .\build\native-image.jar -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime
- env:
- JAVA_HOME: ./graalvm-ce-java11-21.3.0
+ run: native-image.cmd -cp .\build\native-image.jar -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime
- name: Smoke Test
if: success()
shell: cmd
diff --git a/attribution.txt b/attribution.txt
index e3879aa..75d4a50 100644
--- a/attribution.txt
+++ b/attribution.txt
@@ -1955,7 +1955,7 @@ limitations under the License.
-------------------------------------------------------------------------------------------------------------------------------
-Package: org.apache.maven:maven-model:3.6.3
+Package: org.apache.maven:maven-model:3.8.4
License: Apache-2.0
diff --git a/enforcer/file/maven/pom.xml b/enforcer/file/maven/pom.xml
index fba5aea..699b4cf 100644
--- a/enforcer/file/maven/pom.xml
+++ b/enforcer/file/maven/pom.xml
@@ -27,7 +27,7 @@
org.apache.maven
maven-model
- 3.6.3
+ ${maven.version}
compile
From 915366dab64f8a0ee05b519791f2312964c2621c Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 20:13:46 -0500
Subject: [PATCH 10/31] remote-repository: Login to GHCR with correct creds
---
.github/workflows/maven-ci.yml | 4 ++--
.github/workflows/release.yml | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index c70b4f6..423c1b0 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -65,8 +65,8 @@ jobs:
uses: docker/login-action@v1
with:
registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
+ username: ${{ secrets.GIT_USERNAME }}
+ password: ${{ secrets.GIT_PACKAGE_TOKEN }}
- name: Set Maven Project Version
shell: bash
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2cea482..bf4aeb7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -41,8 +41,8 @@ jobs:
uses: docker/login-action@v1
with:
registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
+ username: ${{ secrets.GIT_USERNAME }}
+ password: ${{ secrets.GIT_PACKAGE_TOKEN }}
- name: Set Maven Project Version
id: set_maven_project_version
shell: bash
From 31c48bf5040b7acccc9a5140ec56c4b184d16a41 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 20:39:42 -0500
Subject: [PATCH 11/31] remote-repository: Update static native imate to be
-H:+StaticExecutableWithDynamicLibC
---
.../native-image/sourcehawk-cli/native-image.properties | 3 +--
.../com/optum/sourcehawk/cli/NativeImageConfigSpec.groovy | 1 -
distributions/linux/native-image-builder/Dockerfile | 4 ++--
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/cli/src/main/resources/META-INF/native-image/sourcehawk-cli/native-image.properties b/cli/src/main/resources/META-INF/native-image/sourcehawk-cli/native-image.properties
index 10ea548..57ad3db 100644
--- a/cli/src/main/resources/META-INF/native-image/sourcehawk-cli/native-image.properties
+++ b/cli/src/main/resources/META-INF/native-image/sourcehawk-cli/native-image.properties
@@ -1,3 +1,2 @@
Args = -H:Class=${cli.class} \
- -H:Name=${cli.name} \
- --no-server
\ No newline at end of file
+ -H:Name=${cli.name}
\ No newline at end of file
diff --git a/cli/src/test/groovy/com/optum/sourcehawk/cli/NativeImageConfigSpec.groovy b/cli/src/test/groovy/com/optum/sourcehawk/cli/NativeImageConfigSpec.groovy
index e657673..85ad9bc 100644
--- a/cli/src/test/groovy/com/optum/sourcehawk/cli/NativeImageConfigSpec.groovy
+++ b/cli/src/test/groovy/com/optum/sourcehawk/cli/NativeImageConfigSpec.groovy
@@ -19,7 +19,6 @@ class NativeImageConfigSpec extends Specification {
then:
args.contains("-H:Class=${Sourcehawk.name}")
args.contains("-H:Name=sourcehawk")
- args.contains("--no-server")
}
def "all native image configs are on classpath"() {
diff --git a/distributions/linux/native-image-builder/Dockerfile b/distributions/linux/native-image-builder/Dockerfile
index 2551249..23d2770 100644
--- a/distributions/linux/native-image-builder/Dockerfile
+++ b/distributions/linux/native-image-builder/Dockerfile
@@ -15,6 +15,6 @@ WORKDIR ${WORKDIR}
# Build the native image
RUN native-image -cp native-image.jar \
-H:+ReportExceptionStackTraces \
+ -H:+StaticExecutableWithDynamicLibC \
--report-unsupported-elements-at-runtime \
- --no-fallback \
- --static
\ No newline at end of file
+ --no-fallback
\ No newline at end of file
From 0dbbc017013b3d15bed3be65f55e4d033527b0c1 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Thu, 6 Jan 2022 21:03:58 -0500
Subject: [PATCH 12/31] remote-repository: Update busybox
---
distributions/docker/Dockerfile | 2 +-
distributions/linux/native-image-builder/Dockerfile | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/distributions/docker/Dockerfile b/distributions/docker/Dockerfile
index 8bb6827..5b3d26b 100644
--- a/distributions/docker/Dockerfile
+++ b/distributions/docker/Dockerfile
@@ -1,5 +1,5 @@
# glibc is required for proper DNS resolution within app
-FROM busybox:1.32.0-glibc
+FROM busybox:1.35.0-glibc
# Dynamically pass in name
ARG NAME="sourcehawk"
diff --git a/distributions/linux/native-image-builder/Dockerfile b/distributions/linux/native-image-builder/Dockerfile
index 23d2770..2551249 100644
--- a/distributions/linux/native-image-builder/Dockerfile
+++ b/distributions/linux/native-image-builder/Dockerfile
@@ -15,6 +15,6 @@ WORKDIR ${WORKDIR}
# Build the native image
RUN native-image -cp native-image.jar \
-H:+ReportExceptionStackTraces \
- -H:+StaticExecutableWithDynamicLibC \
--report-unsupported-elements-at-runtime \
- --no-fallback
\ No newline at end of file
+ --no-fallback \
+ --static
\ No newline at end of file
From fe26db44f6ed86cd05ce22f481102c8a911ce4be Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 16:07:00 -0500
Subject: [PATCH 13/31] remote-repository: Static native image builds on musl,
scratch Docker image, disabling Bintray publish
---
.github/workflows/maven-ci.yml | 2 +-
.github/workflows/release.yml | 33 ++
.gitignore | 1 +
NOTICE.txt | 2 +-
attribution.txt | 2 +-
cli/pom.xml | 2 +-
cli/scripts/update-picocli.sh | 22 +-
.../cli/AbstractRemoteScanCommand.java | 2 +-
.../com/optum/sourcehawk/cli/Sourcehawk.java | 2 +-
cli/src/main/java/picocli/CommandLine.java | 168 ++++++---
distributions/debian/pom.xml | 181 +++++-----
.../docker-builders/Dockerfile-nativeimage | 15 +-
distributions/docker/Dockerfile | 22 +-
distributions/docker/README.md | 6 +-
distributions/docker/etc/group | 1 +
distributions/docker/etc/passwd | 1 +
distributions/docker/pom.xml | 30 +-
.../linux/native-image-builder/Dockerfile | 3 +-
distributions/linux/pom.xml | 56 ++-
distributions/rpm/pom.xml | 325 ++++++++----------
.../scripts/build-and-push-docker-builders.sh | 4 -
21 files changed, 496 insertions(+), 384 deletions(-)
create mode 100644 distributions/docker/etc/group
create mode 100644 distributions/docker/etc/passwd
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index 423c1b0..5ff5f60 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -126,7 +126,7 @@ jobs:
steps:
- uses: actions/download-artifact@v2
with:
- name: native-image-8
+ name: native-image-11
path: build
- uses: actions/download-artifact@v2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bf4aeb7..bfa76b4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -149,6 +149,17 @@ jobs:
asset_path: ./distributions/debian/target/sourcehawk-ubuntu-focal.deb
asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-ubuntu-focal-amd64.deb
asset_content_type: application/octet-stream
+ - name: Upload Sourcehawk Centos 7 RPM Package
+ if: success()
+ continue-on-error: true
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./distributions/rpm/target/sourcehawk-centos-7.rpm
+ asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.el7.x86_64.rpm
+ asset_content_type: application/octet-stream
- name: Upload Sourcehawk Centos 8 RPM Package
if: success()
continue-on-error: true
@@ -160,6 +171,28 @@ jobs:
asset_path: ./distributions/rpm/target/sourcehawk-centos-8.rpm
asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.el8.x86_64.rpm
asset_content_type: application/octet-stream
+ - name: Upload Sourcehawk Fedora 33 RPM Package
+ if: success()
+ continue-on-error: true
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./distributions/rpm/target/sourcehawk-fedora-33.rpm
+ asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.fc33.x86_64.rpm
+ asset_content_type: application/octet-stream
+ - name: Upload Sourcehawk Fedora 34 RPM Package
+ if: success()
+ continue-on-error: true
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./distributions/rpm/target/sourcehawk-fedora-34.rpm
+ asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.fc34.x86_64.rpm
+ asset_content_type: application/octet-stream
- name: Upload Sourcehawk Fedora 35 RPM Package
if: success()
continue-on-error: true
diff --git a/.gitignore b/.gitignore
index 0e332c5..6028a98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ target/
*.log
log
logs
+*.bak
### STS ###
.apt_generated
diff --git a/NOTICE.txt b/NOTICE.txt
index 15afa52..4fc5b89 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,6 +1,6 @@
sourcehawk
-Copyright 2021 Optum
+Copyright 2022 Optum
Project Description:
====================
diff --git a/attribution.txt b/attribution.txt
index 75d4a50..fc3dc30 100644
--- a/attribution.txt
+++ b/attribution.txt
@@ -2230,7 +2230,7 @@ http://www.apache.org/licenses/LICENSE-2.0
-------------------------------------------------------------------------------------------------------------------------------
-Package: info.picocli:4.6.1
+Package: info.picocli:4.6.2
License: Apache-2.0
diff --git a/cli/pom.xml b/cli/pom.xml
index aeb3dee..624debf 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -31,7 +31,7 @@
**/picocli/**/*.*
- 4.6.1
+ 4.6.2
diff --git a/cli/scripts/update-picocli.sh b/cli/scripts/update-picocli.sh
index f4619ee..3d35f7d 100755
--- a/cli/scripts/update-picocli.sh
+++ b/cli/scripts/update-picocli.sh
@@ -11,11 +11,11 @@ set -e
#########################################################################
# Retrieve Latest Version
-VERSION=$(curl -sI https://github.com/remkop/picocli/releases/latest | grep -i location: | awk -F"/" '{ printf "%s", $NF }' | tr -d 'v' | tr -d '\r\n')
+VERSION=$(curl -ksI https://github.com/remkop/picocli/releases/latest | grep -i location: | awk -F"/" '{ printf "%s", $NF }' | tr -d 'v' | tr -d '\r\n')
# Global Variables
-DIR="$( cd "$( dirname "$( dirname "${BASH_SOURCE[0]}" )")" && pwd )"
-ROOT_DIR="$( cd "$( dirname "$( dirname "$( dirname "${BASH_SOURCE[0]}" )")")" && pwd )"
+DIR="$(dirname "$(cd -- "$(dirname "$0")"; pwd -P)")"
+ROOT_DIR="$(dirname "$(dirname "$(cd -- "$(dirname "$0")"; pwd -P)")")"
BASE_URL="https://raw.githubusercontent.com/remkop/picocli"
LICENSE_URL="$BASE_URL/v$VERSION/LICENSE"
LICENSE_FILE_PATH="$DIR/src/main/resources/META-INF/licenses/picocli.txt"
@@ -28,15 +28,19 @@ curl -ksf "$LICENSE_URL" > "$LICENSE_FILE_PATH"
curl -ksf "$SOURCE_URL" > "$SOURCE_FILE_PATH"
# Add some warning suppression to the java source file
-sed -i 's/public\sclass\sCommandLine/@SuppressWarnings({"rawtypes", "deprecation" })\npublic class CommandLine/g' "$SOURCE_FILE_PATH"
+sed -i.bak -e 's/public\sclass\sCommandLine/@SuppressWarnings({"rawtypes", "deprecation" })\npublic class CommandLine/g' \
+ -e 's/TODO/TIDO/g' "$SOURCE_FILE_PATH" \
+ && rm -rf "$SOURCE_FILE_PATH.bak"
+
+# Remove TODOs so not highlighted in editor
+sed -i.bak 's/TODO/TIDO/g' "$SOURCE_FILE_PATH"
# Replace the version in pom.xml file for plugin references
-sed -i "s/[-[:alnum:]./]\{1,\}<\/picocli.version>/$VERSION<\/picocli.version>/" "$DIR/pom.xml"
+sed -i.bak "s/[-[:alnum:]./]\{1,\}<\/picocli.version>/$VERSION<\/picocli.version>/" "$DIR/pom.xml" \
+ && rm -rf "$DIR/pom.xml.bak"
# Replace the version in attribution.txt file
-sed -i "s/Package: info.picocli:[-[:alnum:]./]\{1,\}/Package: info.picocli:$VERSION/" "$ROOT_DIR/attribution.txt"
-
-# Remove TODOs so not highlighted in editor
-sed -i 's/TODO/TIDO/g' "$SOURCE_FILE_PATH"
+sed -i.bak "s/Package: info.picocli:[-[:alnum:]./]\{1,\}/Package: info.picocli:$VERSION/" "$ROOT_DIR/attribution.txt" \
+ && rm -rf "$ROOT_DIR/attribution.txt.bak"
echo "Picocli updated to version: $VERSION"
\ No newline at end of file
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java b/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
index cdae269..fffff82 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/AbstractRemoteScanCommand.java
@@ -43,7 +43,7 @@ abstract class AbstractRemoteScanCommand implements Callable {
*/
@Override
public Integer call() {
- val parentExecOptions = parentCommand.buildExecOptions();
+ val parentExecOptions = parentCommand.buildExecOptions(); // TODO: NPE ??
val execOptionsBuilder = parentExecOptions.toBuilder();
val configFileProvided = Optional.ofNullable(parentCommand.spec)
.map(CommandLine.Model.CommandSpec::commandLine)
diff --git a/cli/src/main/java/com/optum/sourcehawk/cli/Sourcehawk.java b/cli/src/main/java/com/optum/sourcehawk/cli/Sourcehawk.java
index 28f1e86..8840dab 100644
--- a/cli/src/main/java/com/optum/sourcehawk/cli/Sourcehawk.java
+++ b/cli/src/main/java/com/optum/sourcehawk/cli/Sourcehawk.java
@@ -22,7 +22,7 @@
headerHeading = "@|fg(magenta) >_ S O U R C E H A W K|@",
synopsisHeading = "%n",
commandListHeading ="%nCommands:%n",
- footer = "Copyright (c) 2020 Optum",
+ footer = "Copyright (c) 2022 Optum",
versionProvider = Sourcehawk.VersionProvider.class,
subcommands = {
CommandLine.HelpCommand.class,
diff --git a/cli/src/main/java/picocli/CommandLine.java b/cli/src/main/java/picocli/CommandLine.java
index 636662b..a0f8454 100644
--- a/cli/src/main/java/picocli/CommandLine.java
+++ b/cli/src/main/java/picocli/CommandLine.java
@@ -72,7 +72,7 @@
*
* // CheckSum implements Callable, so parsing, error handling and handling user
* // requests for usage help or version help can be done with one line of code.
- * public static void main(String[] args) throws Exception {
+ * public static void main(String[] args) {
* int exitCode = new CommandLine(new CheckSum()).execute(args);
* System.exit(exitCode);
* }
@@ -142,11 +142,10 @@
*
*
*/
-@SuppressWarnings({"rawtypes", "deprecation" })
public class CommandLine {
/** This is picocli version {@value}. */
- public static final String VERSION = "4.6.1";
+ public static final String VERSION = "4.6.2";
private final Tracer tracer = new Tracer();
private CommandSpec commandSpec;
@@ -1207,7 +1206,7 @@ public CommandLine setColorScheme(Help.ColorScheme colorScheme) {
* help with a {@code --help} or similar option, the usage help message is printed to the standard output stream so that it can be easily searched and paged.
* @since 4.0 */
public PrintWriter getOut() {
- if (out == null) { setOut(new PrintWriter(System.out, true)); }
+ if (out == null) { setOut(newPrintWriter(System.out, getStdoutEncoding())); }
return out;
}
@@ -1234,7 +1233,7 @@ public CommandLine setOut(PrintWriter out) {
* should use this writer to print error messages (which may include a usage help message) when an unexpected error occurs.
* @since 4.0 */
public PrintWriter getErr() {
- if (err == null) { setErr(new PrintWriter(System.err, true)); }
+ if (err == null) { setErr(newPrintWriter(System.err, getStderrEncoding())); }
return err;
}
@@ -1808,7 +1807,7 @@ protected R throwOrExit(ExecutionException ex) {
* @since 2.0 */
@Deprecated public static class DefaultExceptionHandler extends AbstractHandler> implements IExceptionHandler, IExceptionHandler2 {
public List handleException(ParameterException ex, PrintStream out, Help.Ansi ansi, String... args) {
- internalHandleParseException(ex, new PrintWriter(out, true), Help.defaultColorScheme(ansi)); return Collections.emptyList(); }
+ internalHandleParseException(ex, newPrintWriter(out, getStdoutEncoding()), Help.defaultColorScheme(ansi)); return Collections.emptyList(); }
/** Prints the message of the specified exception, followed by the usage message for the command or subcommand
* whose input was invalid, to the stream returned by {@link #err()}.
@@ -1818,7 +1817,7 @@ public List handleException(ParameterException ex, PrintStream out, Help
* @return the empty list
* @since 3.0 */
public R handleParseException(ParameterException ex, String[] args) {
- internalHandleParseException(ex, new PrintWriter(err(), true), colorScheme()); return returnResultOrExit(null); }
+ internalHandleParseException(ex, newPrintWriter(err(), getStderrEncoding()), colorScheme()); return returnResultOrExit(null); }
static void internalHandleParseException(ParameterException ex, PrintWriter writer, Help.ColorScheme colorScheme) {
writer.println(colorScheme.errorText(ex.getMessage()));
@@ -1879,7 +1878,7 @@ public static boolean printHelpIfRequested(ParseResult parseResult) {
* @since 3.6 */
@Deprecated public static boolean printHelpIfRequested(List parsedCommands, PrintStream out, PrintStream err, Help.ColorScheme colorScheme) {
// for backwards compatibility
- for (CommandLine cmd : parsedCommands) { cmd.setOut(new PrintWriter(out, true)).setErr(new PrintWriter(err, true)).setColorScheme(colorScheme); }
+ for (CommandLine cmd : parsedCommands) { cmd.setOut(newPrintWriter(out, getStdoutEncoding())).setErr(newPrintWriter(err, getStderrEncoding())).setColorScheme(colorScheme); }
return executeHelpRequest(parsedCommands) != null;
}
@@ -2135,8 +2134,8 @@ private T enrichForBackwardsCompatibility(T obj) {
// and the application called #useOut, #useErr or #useAnsi on it
if (obj instanceof AbstractHandler, ?>) {
AbstractHandler, ?> handler = (AbstractHandler, ?>) obj;
- if (handler.out() != System.out) { setOut(new PrintWriter(handler.out(), true)); }
- if (handler.err() != System.err) { setErr(new PrintWriter(handler.err(), true)); }
+ if (handler.out() != System.out) { setOut(newPrintWriter(handler.out(), getStdoutEncoding())); }
+ if (handler.err() != System.err) { setErr(newPrintWriter(handler.err(), getStderrEncoding())); }
if (handler.ansi() != Help.Ansi.AUTO) { setColorScheme(handler.colorScheme()); }
}
return obj;
@@ -2229,6 +2228,9 @@ private int resolveExitCode(int exitCodeOnSuccess, R executionResult, List> implements IParseResultHandler {
+ /** {@inheritDoc} */
+ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); }
+
/** Prints help if requested, and otherwise executes the top-level {@code Runnable} or {@code Callable} command.
* Finally, either a list of result objects is returned, or the JVM is terminated if an exit code {@linkplain #andExit(int) was set}.
* If the top-level command does not implement either {@code Runnable} or {@code Callable}, an {@code ExecutionException}
@@ -2310,6 +2312,9 @@ protected List extractExitCodeGenerators(ParseResult parseRe
*
* @since 2.0 */
public static class RunLast extends AbstractParseResultHandler> implements IParseResultHandler {
+ /** {@inheritDoc} */
+ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); }
+
/** Prints help if requested, and otherwise executes the most specific {@code Runnable} or {@code Callable} subcommand.
* For {@linkplain Command#subcommandsRepeatable() repeatable subcommands}, this method
* may execute multiple subcommands: the most deeply nested subcommands that have the same parent command.
@@ -2382,6 +2387,9 @@ protected List extractExitCodeGenerators(ParseResult parseRe
* For use by the {@link #execute(String...) execute} method.
* @since 2.0 */
public static class RunAll extends AbstractParseResultHandler> implements IParseResultHandler {
+ /** {@inheritDoc} */
+ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); }
+
/** Prints help if requested, and otherwise executes the top-level command and all subcommands as {@code Runnable},
* {@code Callable} or {@code Method}. Finally, either a list of result objects is returned, or the JVM is terminated if an exit
* code {@linkplain #andExit(int) was set}. If any of the {@code CommandLine} commands does not implement either
@@ -3648,22 +3656,33 @@ public enum ScopeType {
boolean required() default false;
/**
- * Set {@code help=true} if this option should disable validation of the remaining arguments:
- * If the {@code help} option is specified, no error message is generated for missing required options.
- *
- * This attribute is useful for special options like help ({@code -h} and {@code --help} on unix,
- * {@code -?} and {@code -Help} on Windows) or version ({@code -V} and {@code --version} on unix,
- * {@code -Version} on Windows).
+ *
This should rarely be used: the recommended attributes are {@link #usageHelp() usageHelp} and {@link #versionHelp() versionHelp}.
+ *
+ * Only set {@code help=true} when this option should disable validation of the remaining
+ * arguments, and no error message should be generated for missing required options.
+ *
+ * This is useful for custom help options that are in addition to the standard help and
+ * version options. For example if your application has many hidden options or
+ * subcommands, and there is a custom help option like {@code --detailed-help} that prints
+ * the usage help message for these hidden options and subcommands.
*
+ * Note:
*
- * Note that the {@link #parse(String...)} method will not print help documentation. It will only set
- * the value of the annotated field. It is the responsibility of the caller to inspect the annotated fields
- * and take the appropriate action.
+ * Use the {@link #usageHelp() usageHelp} for "normal" help options (like {@code -h} and {@code --help} on unix,
+ * {@code -?} and {@code -Help} on Windows)
+ * and use {@link #versionHelp() versionHelp} for "normal" version help ({@code -V} and {@code --version} on unix,
+ * {@code -Version} on Windows):
+ * picocli has built-in logic so that options with {@code usageHelp=true} or {@code versionHelp=true}
+ * will automatically cause the requested help message to be printed in applications
+ * that use the {@link #execute(String...)} method, without any code in the application.
+ *
+ * Note that there is no such automatic help printing for options with {@code help=true};
+ * applications need to check whether the end user specified this option and take appropriate action
+ * in the business logic of the application.
*
* @return whether this option disables validation of the other arguments
- * @deprecated Use {@link #usageHelp()} and {@link #versionHelp()} instead. See {@link #printHelpIfRequested(List, PrintStream, CommandLine.Help.Ansi)}
*/
- @Deprecated boolean help() default false;
+ boolean help() default false;
/**
* Set {@code usageHelp=true} for the {@code --help} option that triggers display of the usage help message.
@@ -3735,7 +3754,7 @@ public enum ScopeType {
* command line, a {@link MissingParameterException} is thrown by the {@link #parse(String...)} method.
*
* In many cases picocli can deduce the number of required parameters from the field's type.
- * By default, flags (boolean options) have arity zero,
+ * By default, flags (boolean options) have arity "0..1",
* and single-valued type fields (String, int, Integer, double, Double, File, Date, etc) have arity one.
* Generally, fields with types that cannot hold multiple values can omit the {@code arity} attribute.
*
@@ -3747,7 +3766,8 @@ public enum ScopeType {
*
* A note on boolean options
*
- * By default picocli does not expect boolean options (also called "flags" or "switches") to have a parameter.
+ * By default picocli allows boolean options (also called "flags" or "switches") to have an optional parameter,
+ * which must be either "true" or "false" (lowercase, other values are rejected).
* You can make a boolean option take a required parameter by annotating your field with {@code arity="1"}.
* For example:
* @Option(names = "-v", arity = "1") boolean verbose;
@@ -3757,12 +3777,11 @@ public enum ScopeType {
* on the command line, or a {@link MissingParameterException} is thrown by the {@link #parse(String...)}
* method.
*
- * To make the boolean parameter possible but optional, define the field with {@code arity = "0..1"}.
+ * To remove the optional parameter, define the field with {@code arity = "0"}.
* For example:
- * @Option(names="-v", arity="0..1") boolean verbose;
- * This will accept any of the below without throwing an exception:
+ * @Option(names="-v", arity="0") boolean verbose;
+ * This will reject any of the below:
*
- * -v
* -v true
* -v false
*
@@ -4974,6 +4993,8 @@ private static class NoDefaultProvider implements IDefaultValueProvider {
* }
* }
* }
+ * If this interface does not meet your requirements, you may have a look at the more powerful
+ * and flexible {@link IParameterPreprocessor} interface introduced with picocli 4.6.
* @see Option#parameterConsumer()
* @see Parameters#parameterConsumer()
* @since 4.0 */
@@ -5602,9 +5623,14 @@ static Range adjustForType(Range result, IAnnotatedElement member) {
return result.isUnspecified ? defaultArity(member) : result;
}
/** Returns the default arity {@code Range}: for interactive options/positional parameters,
- * this is 0; for {@link Option options} this is 0 for booleans and 1 for
- * other types, for {@link Parameters parameters} booleans have arity 0, arrays or Collections have
+ * this is 0; for {@link Option options} this is effectively "0..1" for booleans and 1 for
+ * other types, for {@link Parameters parameters} booleans have arity 1, arrays or Collections have
* arity "0..*", and other types have arity 1.
+ * Implementation Notes
+ * The returned {@code Range} for boolean options has an effective arity of "0..1".
+ * This is implemented by returning a {@code Range} with arity "0",
+ * and its {@code unspecified} property set to {@code true}.
+ * This implementation may change in the future.
* @param field the field whose default arity to return
* @return a new {@code Range} indicating the default arity of the specified field
* @since 2.0 */
@@ -6386,7 +6412,7 @@ public CommandSpec addSubcommand(String name, CommandSpec subcommand) {
*/
public CommandSpec addSubcommand(String name, CommandLine subCommandLine) {
CommandSpec subSpec = subCommandLine.getCommandSpec();
- String actualName = validateSubcommandName(name, subSpec);
+ String actualName = validateSubcommandName(interpolator.interpolateCommandName(name), subSpec);
Tracer t = new Tracer();
if (t.isDebug()) {t.debug("Adding subcommand '%s' to '%s'%n", actualName, this.qualifiedName());}
String previousName = commands.getCaseSensitiveKey(actualName);
@@ -6396,7 +6422,7 @@ public CommandSpec addSubcommand(String name, CommandLine subCommandLine) {
subSpec.parent(this);
for (String alias : subSpec.aliases()) {
if (t.isDebug()) {t.debug("Adding alias '%s' for '%s'%n", (parent == null ? "" : parent.qualifiedName() + " ") + alias, this.qualifiedName());}
- previous = commands.put(alias, subCommandLine);
+ previous = commands.put(interpolator.interpolate(alias), subCommandLine);
if (previous != null && previous != subCommandLine) { throw new DuplicateNameException("Alias '" + alias + "' for subcommand '" + actualName + "' is already used by another subcommand of '" + this.name() + "'"); }
}
subSpec.initCommandHierarchyWithResourceBundle(resourceBundleBaseName(), resourceBundle());
@@ -6424,8 +6450,8 @@ private void inheritAttributesFrom(CommandSpec root) {
updatedSubcommandsToInheritFrom(root);
}
private void updatedSubcommandsToInheritFrom(CommandSpec root) {
- if (root != this) {
- mixinStandardHelpOptions(root.mixinStandardHelpOptions());
+ if (root != this && root.mixinStandardHelpOptions()) { // #1331 only add, don't remove
+ mixinStandardHelpOptions(true);
}
Set subcommands = new HashSet(subcommands().values());
for (CommandLine sub : subcommands) {
@@ -6702,6 +6728,7 @@ public CommandSpec remove(ArgSpec arg) {
if (positionalParameters.remove(arg)) {
removed++;
}
+ args.remove(arg);
if (removed == 0) {
throw new NoSuchElementException(String.valueOf(arg));
}
@@ -6936,7 +6963,8 @@ public Set names() {
public List args() { return Collections.unmodifiableList(args); }
Object[] commandMethodParamValues() {
Object[] values = new Object[methodParams.length];
- int argIndex = mixins.containsKey(AutoHelpMixin.KEY) ? 2 : 0;
+ CommandSpec autoHelpMixin = mixins.get(AutoHelpMixin.KEY);
+ int argIndex = autoHelpMixin == null || autoHelpMixin.inherited() ? 0 : 2;
for (int i = 0; i < methodParams.length; i++) {
if (methodParams[i].isAnnotationPresent(Mixin.class)) {
String name = methodParams[i].getAnnotation(Mixin.class).name();
@@ -7155,7 +7183,20 @@ public CommandSpec negatableOptionTransformer(INegatableOptionTransformer newVal
public CommandSpec mixinStandardHelpOptions(boolean newValue) {
if (newValue) {
CommandSpec mixin = CommandSpec.forAnnotatedObject(new AutoHelpMixin(), new DefaultFactory());
- addMixin(AutoHelpMixin.KEY, mixin);
+ boolean overlap = false;
+ for (String key : mixin.optionsMap().keySet()) {
+ if (optionsMap().containsKey(key)) { overlap = true; break; }
+ }
+ if (!overlap) { // #1316, 1319 avoid DuplicateOptionAnnotationsException
+ mixin.inherited = this.inherited();
+ addMixin(AutoHelpMixin.KEY, mixin);
+ }
+ // #1331 if inherit(ed) we also add to subcommands
+ if (scopeType() == ScopeType.INHERIT || inherited()) {
+ for (CommandLine sub : new HashSet(subcommands().values())) {
+ sub.getCommandSpec().mixinStandardHelpOptions(newValue);
+ }
+ }
} else {
CommandSpec helpMixin = mixins.remove(AutoHelpMixin.KEY);
if (helpMixin != null) {
@@ -7167,11 +7208,7 @@ public CommandSpec mixinStandardHelpOptions(boolean newValue) {
}
}
}
- }
- if (scopeType() == ScopeType.INHERIT || inherited()) {
- for (CommandLine sub : new HashSet(subcommands().values())) {
- sub.getCommandSpec().mixinStandardHelpOptions(newValue);
- }
+ // #1331 we don't remove StandardHelpOptions from subcommands, even if they inherit from us
}
return this;
}
@@ -8669,10 +8706,20 @@ public String[] description() {
private String[] expandVariables(String[] desc) {
if (desc.length == 0) { return desc; }
StringBuilder candidates = new StringBuilder();
- if (completionCandidates() != null) {
- for (String c : completionCandidates()) {
- if (candidates.length() > 0) { candidates.append(", "); }
- candidates.append(c);
+ boolean isCompletionCandidatesUsed = false;
+ for (String s: desc) {
+ if (s.contains(DESCRIPTION_VARIABLE_COMPLETION_CANDIDATES)) {
+ isCompletionCandidatesUsed = true;
+ break;
+ }
+ }
+ if (isCompletionCandidatesUsed) {
+ Iterable iter = completionCandidates();
+ if (iter != null) {
+ for (String c : iter) {
+ if (candidates.length() > 0) { candidates.append(", "); }
+ candidates.append(c);
+ }
}
}
String defaultValueString = defaultValueString(false); // interpolate later
@@ -8740,7 +8787,7 @@ private String[] expandVariables(String[] desc) {
/** Returns the root option or positional parameter (on the parent command), if this option or positional parameter was inherited;
* or {@code null} if it was not.
* @see Option#scope()
- * @since 4.6.1 */
+ * @since 4.6.2 */
public ArgSpec root() { return root; }
/** Returns the type to convert the option or positional parameter to before {@linkplain #setValue(Object) setting} the value.
@@ -8787,8 +8834,10 @@ public String mapFallbackValue() {
public Object initialValue() {
// not not initialize if already CACHED, or UNAVAILABLE, or if annotatedElement==null
if (initialValueState == InitialValueState.POSTPONED && annotatedElement != null) {
- try { initialValue = annotatedElement.getter().get(); } catch (Exception ex) { }
- initialValueState = InitialValueState.CACHED;
+ try {
+ initialValue = annotatedElement.getter().get();
+ initialValueState = InitialValueState.CACHED; // only if successfully initialized
+ } catch (Exception ex) { } // #1300 if error: keep initialValueState == POSTPONED
}
return initialValue;
}
@@ -9376,7 +9425,7 @@ private static String inferLabel(String label, String fieldName, ITypeInfo typeI
/** Returns the root option or positional parameter (on the parent command), if this option or positional parameter was inherited;
* or {@code null} if it was not.
* @see Option#scope()
- * @since 4.6.1 */
+ * @since 4.6.2 */
public ArgSpec root() { return root; }
/** Returns the type to convert the option or positional parameter to before {@linkplain #setValue(Object) setting} the value.
@@ -9519,7 +9568,7 @@ private static String inferLabel(String label, String fieldName, ITypeInfo typeI
/**
* Sets the root object for this inherited option, and returns this builder.
- * @since 4.6.1 */
+ * @since 4.6.2 */
public T root(ArgSpec root) { this.root = root ; return self(); }
/** Sets the type to convert the option or positional parameter to before {@linkplain #setValue(Object) setting} the value, and returns this builder.
@@ -13264,12 +13313,14 @@ private void processArguments(List parsedCommands,
if (commandSpec.parent() != null && commandSpec.parent().subcommandsRepeatable() && commandSpec.parent().subcommands().containsKey(arg)) {
tracer.debug("'%s' is a repeatable subcommand of %s%n", arg, commandSpec.parent().qualifiedName());// #454 repeatable subcommands
CommandLine subcommand = commandSpec.parent().subcommands().get(arg);
+ Set inheritedInitialized = initialized;
if (subcommand.interpreter.parseResultBuilder != null) {
tracer.debug("Subcommand '%s' has been matched before. Making a copy...%n", subcommand.getCommandName());
subcommand = subcommand.copy();
subcommand.getCommandSpec().parent(commandSpec.parent()); // hook it up with its parent
+ inheritedInitialized = new LinkedHashSet(inheritedInitialized);
}
- processSubcommand(subcommand, getParent().interpreter.parseResultBuilder, parsedCommands, args, required, initialized, originalArgs, nowProcessing, separator, arg);
+ processSubcommand(subcommand, getParent().interpreter.parseResultBuilder, parsedCommands, args, required, inheritedInitialized, originalArgs, nowProcessing, separator, arg);
continue;
}
@@ -14387,7 +14438,9 @@ private static String optionDescription(String prefix, ArgSpec argSpec, int opti
if (argSpec.arity().max > 1) {
desc += " at index " + optionParamIndex;
}
- desc += " (" + argSpec.paramLabel() + ")";
+ if (argSpec.arity().max > 0) {
+ desc += " (" + argSpec.paramLabel() + ")";
+ }
}
} else {
desc = prefix + "positional parameter at index " + ((PositionalParamSpec) argSpec).index() + " (" + argSpec.paramLabel() + ")";
@@ -14469,6 +14522,17 @@ static void close(Closeable closeable) {
new Tracer().warn("Could not close " + closeable + ": " + ex.toString());
}
}
+ static Charset getStdoutEncoding() {
+ String encoding = System.getProperty("sun.stdout.encoding");
+ return encoding != null ? Charset.forName(encoding) : Charset.defaultCharset();
+ }
+ static Charset getStderrEncoding() {
+ String encoding = System.getProperty("sun.stderr.encoding");
+ return encoding != null ? Charset.forName(encoding) : Charset.defaultCharset();
+ }
+ static PrintWriter newPrintWriter(OutputStream stream, Charset charset) {
+ return new PrintWriter(new BufferedWriter(new OutputStreamWriter(stream, charset)), true);
+ }
static class PositionalParametersSorter implements Comparator {
private static final Range OPTION_INDEX = new Range(0, 0, false, true, "0");
public int compare(ArgSpec p1, ArgSpec p2) {
@@ -18008,7 +18072,7 @@ static List stripErrorMessage(List unmatched) {
public boolean isUnknownOption() { return isUnknownOption(unmatched, getCommandLine()); }
/** Returns {@code true} and prints suggested solutions to the specified stream if such solutions exist, otherwise returns {@code false}.
* @since 3.3.0 */
- public boolean printSuggestions(PrintStream out) { return printSuggestions(new PrintWriter(out, true)); }
+ public boolean printSuggestions(PrintStream out) { return printSuggestions(newPrintWriter(out, getStdoutEncoding())); }
/** Returns {@code true} and prints suggested solutions to the specified stream if such solutions exist, otherwise returns {@code false}.
* @since 4.0 */
public boolean printSuggestions(PrintWriter writer) {
diff --git a/distributions/debian/pom.xml b/distributions/debian/pom.xml
index 359aeec..16963e4 100644
--- a/distributions/debian/pom.xml
+++ b/distributions/debian/pom.xml
@@ -280,95 +280,96 @@
-
-
- debian-package-release
-
-
- ci.release
-
-
-
-
-
-
-
- debian-package-snapshot
-
-
- ci.snapshot
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- dev-snapshots
-
-
-
-
-
-
-
- debian-package-publish
-
-
- ci.deploy
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- ${bintray.organization}
- ${debian.package}
- ${debian.package.version}${debian.package.version.suffix}
- ${debian.architecture},i386,x86_64
-
-
-
-
- publish-debian-buster-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${debian.package}-debian-buster.deb
- deb
- buster,jessie,stretch
-
-
-
-
- publish-ubuntu-focal-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${debian.package}-ubuntu-focal.deb
- ubuntu
- focal
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index d06225e..d92e389 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -3,4 +3,17 @@ ARG FROM=ghcr.io/graalvm/graalvm-ce:java8-21.2.0
FROM ${FROM}
# Install native-image tool
-RUN gu install --no-progress native-image
\ No newline at end of file
+RUN gu install --no-progress native-image
+
+# Install musl
+RUN curl -L -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
+ && tar -xvf x86_64-linux-musl-native.tgz -C /usr/local/bin \
+ && export CC=/usr/local/bin/x86_64-linux-musl-native/bin/gcc \
+ && curl -kL -o zlib-1.2.11.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
+ && tar -xvf zlib-1.2.11.tar.gz \
+ && cd zlib-1.2.11 \
+ && ./configure --prefix=${WORKDIR}/x86_64-linux-musl-native --static \
+ && make \
+ && make install
+
+ENV PATH="${PATH}:${WORKDIR}/x86_64-linux-musl-native/bin"
\ No newline at end of file
diff --git a/distributions/docker/Dockerfile b/distributions/docker/Dockerfile
index 5b3d26b..168bf95 100644
--- a/distributions/docker/Dockerfile
+++ b/distributions/docker/Dockerfile
@@ -1,23 +1,17 @@
-# glibc is required for proper DNS resolution within app
-FROM busybox:1.35.0-glibc
+FROM scratch
-# Dynamically pass in name
ARG NAME="sourcehawk"
-# Setup user and group
-ENV GROUP=${NAME} USER=${NAME}
-RUN addgroup ${GROUP} && adduser -h /home/${USER} -G ${NAME} -D ${USER}
+# Copy Group and User Files
+COPY "/etc" "/etc"
# Copy the native image executable into the image
-ARG NATIVE_IMAGE_PATH
-COPY --chown=${GROUP}:${USER} ${NATIVE_IMAGE_PATH} /usr/bin/sourcehawk
-
-# Give the native image executable permissions
-RUN chmod +x /usr/bin/${NAME}
+COPY --chown="${NAME}":"${NAME}" "target/native-image" "/entrypoint"
# Set the user and working directory
-USER ${USER}
-WORKDIR /home/${USER}
+USER "${NAME}"
+WORKDIR "/work"
# Set the native image as the entrypoint
-ENTRYPOINT ["/usr/bin/sourcehawk"]
\ No newline at end of file
+CMD ["--help"]
+ENTRYPOINT ["/entrypoint"]
\ No newline at end of file
diff --git a/distributions/docker/README.md b/distributions/docker/README.md
index ec3aa6d..7528041 100644
--- a/distributions/docker/README.md
+++ b/distributions/docker/README.md
@@ -1,15 +1,15 @@
-# Sourcehawk Alpine Docker Image
+# Sourcehawk Docker Image
### Scanning from local directory
```shell script
-docker run -v "$(pwd):/home/sourcehawk" optumopensource/sourcehawk:1.0.0-alpine
+docker run --rm -v $PWD:/work optumopensource/sourcehawk
```
Or with a custom working directory:
```shell script
-docker run -v "$(pwd):/tmp" -w /tmp optumopensource/sourcehawk:1.0.0-alpine
+docker run --rm -v $PWD:/tmp -w /tmp optumopensource/sourcehawk
```
The volume mounting is necessary in order to give the container access to the files to scan.
\ No newline at end of file
diff --git a/distributions/docker/etc/group b/distributions/docker/etc/group
new file mode 100644
index 0000000..0d9e16b
--- /dev/null
+++ b/distributions/docker/etc/group
@@ -0,0 +1 @@
+sourcehawk:x:1000:sourcehawk
\ No newline at end of file
diff --git a/distributions/docker/etc/passwd b/distributions/docker/etc/passwd
new file mode 100644
index 0000000..f96df68
--- /dev/null
+++ b/distributions/docker/etc/passwd
@@ -0,0 +1 @@
+sourcehawk:x:1000:1000:Sourcehawk User,,,:/home/sourcehawk:/entrypoint
\ No newline at end of file
diff --git a/distributions/docker/pom.xml b/distributions/docker/pom.xml
index bb59e6f..2b33223 100644
--- a/distributions/docker/pom.xml
+++ b/distributions/docker/pom.xml
@@ -61,6 +61,30 @@
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+
+
+ update-native-image-permissions
+ prepare-package
+
+ exec
+
+
+ chmod
+
+ +x
+ target/native-image
+
+
+
+
+
+
com.spotify
@@ -76,10 +100,6 @@
${docker.repository}
${docker.tag}
-
- ${global.project.name}
- target/native-image
-
true
@@ -103,6 +123,7 @@
docker
run
+ --rm
${docker.repository}:${docker.tag}
--version
@@ -119,6 +140,7 @@
${maven.multiModuleProjectDirectory}
run
+ --rm
-v
${maven.multiModuleProjectDirectory}:/home/sourcehawk
${docker.repository}:${docker.tag}
diff --git a/distributions/linux/native-image-builder/Dockerfile b/distributions/linux/native-image-builder/Dockerfile
index 2551249..59aefa9 100644
--- a/distributions/linux/native-image-builder/Dockerfile
+++ b/distributions/linux/native-image-builder/Dockerfile
@@ -1,4 +1,4 @@
-ARG GRAALVM_VERSION=21.2.0-java8
+ARG GRAALVM_VERSION=21.3.0-java11
FROM ghcr.io/optum/ci/nativeimage:graalvm-ce-${GRAALVM_VERSION}
# Build Arguments
@@ -17,4 +17,5 @@ RUN native-image -cp native-image.jar \
-H:+ReportExceptionStackTraces \
--report-unsupported-elements-at-runtime \
--no-fallback \
+ --libc=musl \
--static
\ No newline at end of file
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 610b8ea..855bc85 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -193,12 +193,55 @@
+
+
+ windows
+
+
+ windows
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+ true
+
+
+
+
+
+
+
+
+ mac
+
+
+ mac
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+ true
+
+
+
+
+
+
linux-integration-tests
unix
+ Linux
@@ -229,17 +272,6 @@
-
-
- native-image-build-java8
-
- 8
-
-
- 21.2.0-java8
-
-
-
native-image-build-java11
@@ -255,7 +287,7 @@
native-image-build-java17
- 11
+ 17
21.3.0-java17
diff --git a/distributions/rpm/pom.xml b/distributions/rpm/pom.xml
index 10bac32..6dfbb23 100644
--- a/distributions/rpm/pom.xml
+++ b/distributions/rpm/pom.xml
@@ -193,23 +193,6 @@
-
- build-and-tag-fedora-32
- prepare-package
-
- build
- tag
-
-
- ${project.artifactId}-builder-fedora-32
- ${project.version}
-
- fedora32
- /tmp/${rpm.package}-fedora-32.rpm
-
- true
-
-
build-and-tag-fedora-33
prepare-package
@@ -314,21 +297,6 @@
-
- extract-fedora-32-package
- package
-
- exec
-
-
- ${project.parent.basedir}/scripts/extract-file-from-docker-container.sh
-
- ${project.artifactId}-builder-fedora-32:${project.version}
- /tmp/${rpm.package}-fedora-32.rpm
- ${project.build.directory}
-
-
-
extract-fedora-33-package
package
@@ -413,11 +381,6 @@
el8.${rpm.package.architecture}
rpm
-
- ${project.build.directory}/${rpm.package}-fedora-32.rpm
- fc32.${rpm.package.architecture}
- rpm
-
${project.build.directory}/${rpm.package}-fedora-33.rpm
fc33.${rpm.package.architecture}
@@ -442,156 +405,142 @@
-
-
- rpm-package-release
-
-
- ci.release
-
-
-
- 1
-
-
-
- rpm-package-snapshot
-
-
- ci.snapshot
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- dev-snapshots
-
-
-
-
-
-
-
- rpm-package-publish
-
-
- ci.deploy
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- ${bintray.organization}
- ${rpm.package}
- ${rpm.package.version}
- ${rpm.package.release}
- ${rpm.package.architecture}
-
-
-
-
- publish-centos-7-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-centos-7.rpm
- centos
- el7
-
-
-
-
- publish-centos-8-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-centos-8.rpm
- centos
- el8
-
-
-
-
- publish-fedora-32-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-fedora-32.rpm
- fedora
- fc32
-
-
-
-
- publish-fedora-33-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-fedora-33.rpm
- fedora
- fc33
-
-
-
-
- publish-fedora-34-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-fedora-34.rpm
- fedora
- fc34
-
-
-
-
- publish-fedora-35-package
-
- exec
-
- deploy
-
- ${project.basedir}/scripts/publish-package-version-to-bintray.sh
-
- ${project.build.directory}/${rpm.package}-fedora-35.rpm
- fedora
- fc35
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/distributions/scripts/build-and-push-docker-builders.sh b/distributions/scripts/build-and-push-docker-builders.sh
index b0996ab..3bdf453 100755
--- a/distributions/scripts/build-and-push-docker-builders.sh
+++ b/distributions/scripts/build-and-push-docker-builders.sh
@@ -19,25 +19,21 @@ REGISTRY="ghcr.io"
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin $REGISTRY
# Native Image
-docker build -t $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.2.0-java8 -f "$DOCKER_BUILDERS_DIR/Dockerfile-nativeimage" --build-arg FROM=ghcr.io/graalvm/graalvm-ce:java8-21.2.0 .
docker build -t $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java11 -f "$DOCKER_BUILDERS_DIR/Dockerfile-nativeimage" --build-arg FROM=ghcr.io/graalvm/graalvm-ce:java11-21.3.0 .
docker build -t $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java17 -f "$DOCKER_BUILDERS_DIR/Dockerfile-nativeimage" --build-arg FROM=ghcr.io/graalvm/graalvm-ce:java17-21.3.0 .
# RPM Build
docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:centos7 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=centos:7 .
docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:centos8 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=centos:8 .
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora32 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:32 .
docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora33 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:33 .
docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora34 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:34 .
docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora35 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:35 .
# Push All Builders to Remote Registry
-docker push $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.2.0-java8
docker push $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java11
docker push $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java17
docker push $REGISTRY/$DOCKER_ORG/rpmbuild:centos7
docker push $REGISTRY/$DOCKER_ORG/rpmbuild:centos8
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora32
docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora33
docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora34
docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora35
From 0c75dfe4a7e5c19392878b759095f800de7eb1bb Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 16:24:52 -0500
Subject: [PATCH 14/31] remote-repository: Update github workflows
---
.github/workflows/maven-ci.yml | 12 ++++--------
.github/workflows/release.yml | 8 ++++----
distributions/docker-builders/Dockerfile-nativeimage | 2 +-
3 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index 5ff5f60..d96bce6 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -130,24 +130,20 @@ jobs:
path: build
- uses: actions/download-artifact@v2
with:
- name: bash-completion-script-8
+ name: bash-completion-script-11
path: build
- uses: actions/download-artifact@v2
with:
- name: manpages-8
+ name: manpages-11
path: build
- name: Rename Native Image JAR
working-directory: build
run: mv *.jar native-image.jar
- - name: Setup Java
- uses: actions/setup-java@v1
- with:
- java-version: 8
- name: Setup GraalVM
uses: graalvm/setup-graalvm@v1
with:
- version: '21.2.0'
- java-version: '8'
+ version: '21.3.0'
+ java-version: '11'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Mac Native Image
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bfa76b4..8069a29 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -247,7 +247,7 @@ jobs:
steps:
- uses: actions/download-artifact@v2
with:
- name: native-image
+ name: native-image-java11
path: build
- uses: actions/download-artifact@v2
with:
@@ -263,12 +263,12 @@ jobs:
- name: Setup Java
uses: actions/setup-java@v1
with:
- java-version: 8
+ java-version: 11
- name: Setup GraalVM
uses: graalvm/setup-graalvm@v1
with:
- version: '21.2.0'
- java-version: '8'
+ version: '21.3.0'
+ java-version: '11'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Mac Native Image
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index d92e389..1bc2782 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -1,5 +1,5 @@
# Oracle GraalVM Java 8 Base Container
-ARG FROM=ghcr.io/graalvm/graalvm-ce:java8-21.2.0
+ARG FROM=ghcr.io/graalvm/graalvm-ce:java11-21.3.0
FROM ${FROM}
# Install native-image tool
From 80531bc331b562c05f9b02fffc986936b5dcbdc7 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 16:39:52 -0500
Subject: [PATCH 15/31] remote-repository: Fix native image builder and push
to ghcr
---
.../docker-builders/Dockerfile-nativeimage | 6 +--
distributions/docker/pom.xml | 47 +++++++++++++++++--
...-to-docker-hub.sh => push-docker-image.sh} | 0
3 files changed, 44 insertions(+), 9 deletions(-)
rename distributions/docker/scripts/{push-docker-image-to-docker-hub.sh => push-docker-image.sh} (100%)
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index 1bc2782..2056017 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -5,15 +5,13 @@ FROM ${FROM}
# Install native-image tool
RUN gu install --no-progress native-image
-# Install musl
+# Install musl libc
RUN curl -L -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
&& tar -xvf x86_64-linux-musl-native.tgz -C /usr/local/bin \
&& export CC=/usr/local/bin/x86_64-linux-musl-native/bin/gcc \
&& curl -kL -o zlib-1.2.11.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
&& tar -xvf zlib-1.2.11.tar.gz \
&& cd zlib-1.2.11 \
- && ./configure --prefix=${WORKDIR}/x86_64-linux-musl-native --static \
+ && ./configure --prefix=/usr/local/bin/x86_64-linux-musl-native --static \
&& make \
&& make install
-
-ENV PATH="${PATH}:${WORKDIR}/x86_64-linux-musl-native/bin"
\ No newline at end of file
diff --git a/distributions/docker/pom.xml b/distributions/docker/pom.xml
index 2b33223..1a11871 100644
--- a/distributions/docker/pom.xml
+++ b/distributions/docker/pom.xml
@@ -19,6 +19,7 @@
${project.version}
+ ghcr.io/optum/sourcehawk
@@ -91,10 +92,21 @@
dockerfile-maven-plugin
- build-and-tag
+ build
prepare-package
build
+
+
+ ${docker.repository}
+ ${docker.tag}
+ true
+
+
+
+ tag-docker-hub
+ prepare-package
+
tag
@@ -103,6 +115,18 @@
true
+
+ tag-github-container-registry
+ prepare-package
+
+ tag
+
+
+ ${ghcr.repository}
+ ${docker.tag}
+ true
+
+
@@ -142,7 +166,7 @@
run
--rm
-v
- ${maven.multiModuleProjectDirectory}:/home/sourcehawk
+ ${maven.multiModuleProjectDirectory}:/work
${docker.repository}:${docker.tag}
scan
-f
@@ -159,7 +183,7 @@
- docker-hub-push
+ docker-push
ci.release
@@ -172,18 +196,31 @@
exec-maven-plugin
- deploy-docker-image
+ push-docker-image-to-docker-hub
deploy
exec
- ${project.basedir}/scripts/push-docker-image-to-docker-hub.sh
+ ${project.basedir}/scripts/push-docker-image.sh
${docker.repository}:${docker.tag}
+
+ push-docker-image-to-github-container-registry
+ deploy
+
+ exec
+
+
+ ${project.basedir}/scripts/push-docker-image.sh
+
+ ${ghcr.repository}:${docker.tag}
+
+
+
diff --git a/distributions/docker/scripts/push-docker-image-to-docker-hub.sh b/distributions/docker/scripts/push-docker-image.sh
similarity index 100%
rename from distributions/docker/scripts/push-docker-image-to-docker-hub.sh
rename to distributions/docker/scripts/push-docker-image.sh
From 1ddfcf724431adec9491b9c447e4a138497039ad Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 17:40:15 -0500
Subject: [PATCH 16/31] remote-repository: Fix docker image builder for native
image musl, and use github actions for docker layer caching
---
.../build-and-push-docker-builders.yml | 103 +++++++++++++++++-
.github/workflows/maven-ci.yml | 6 -
.github/workflows/release.yml | 6 -
.../docker-builders/Dockerfile-nativeimage | 19 ++--
.../scripts/build-and-push-docker-builders.sh | 42 -------
5 files changed, 108 insertions(+), 68 deletions(-)
delete mode 100755 distributions/scripts/build-and-push-docker-builders.sh
diff --git a/.github/workflows/build-and-push-docker-builders.yml b/.github/workflows/build-and-push-docker-builders.yml
index 2793019..ca8510d 100644
--- a/.github/workflows/build-and-push-docker-builders.yml
+++ b/.github/workflows/build-and-push-docker-builders.yml
@@ -13,9 +13,100 @@ jobs:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.ref }}
- - name: Build and Push Docker Images to Github Container Registry
- shell: bash
- run: ./distributions/scripts/build-and-push-docker-builders.sh
- env:
- DOCKER_USERNAME: ${{ secrets.GIT_USERNAME }}
- DOCKER_PASSWORD: ${{ secrets.GIT_PACKAGE_TOKEN }}
+ - name: Set up Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v1
+ - name: Cache Docker Layers
+ uses: actions/cache@v2
+ with:
+ path: /tmp/.buildx-cache
+ key: ${{ runner.os }}-buildx-${{ github.sha }}
+ restore-keys: |
+ ${{ runner.os }}-buildx-
+ - name: Login to Github Container Registry
+ uses: docker/login-action@v1
+ with:
+ registry: ghcr.io
+ username: ${{ secrets.GIT_USERNAME }}
+ password: ${{ secrets.GIT_PACKAGE_TOKEN }}
+ - name: Build and Push graalvm-ce-21.3.0-java11
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-nativeimage
+ build-args: FROM_VERSION=java11-21.3.0
+ push: false
+ tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java11
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push graalvm-ce-21.3.0-java17
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-nativeimage
+ build-args: FROM_VERSION=java17-21.3.0
+ push: false
+ tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java17
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push rpmbuild centos7
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-rpmbuild
+ build-args: FROM=centos:7
+ push: false
+ tags: ghcr.io/optum/ci/rpmbuild:centos7
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push rpmbuild centos8
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-rpmbuild
+ build-args: FROM=centos:8
+ push: false
+ tags: ghcr.io/optum/ci/rpmbuild:centos8
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push rpmbuild fedora33
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-rpmbuild
+ build-args: FROM=fedora:33
+ push: false
+ tags: ghcr.io/optum/ci/rpmbuild:fedora33
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push rpmbuild fedora34
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-rpmbuild
+ build-args: FROM=fedora:34
+ push: false
+ tags: ghcr.io/optum/ci/rpmbuild:fedora34
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Build and Push rpmbuild fedora35
+ uses: docker/build-push-action@v2
+ with:
+ builder: ${{ steps.buildx.outputs.name }}
+ context: .
+ file: distributions/docker-builders/Dockerfile-rpmbuild
+ build-args: FROM=fedora:35
+ push: false
+ tags: ghcr.io/optum/ci/rpmbuild:fedora35
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
+ - name: Relocate Docker Layer Cache
+ run: |
+ rm -rf /tmp/.buildx-cache
+ mv /tmp/.buildx-cache-new /tmp/.buildx-cache
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index d96bce6..1e92448 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -61,12 +61,6 @@ jobs:
server-password: SONATYPE_PASSWORD
gpg-private-key: ${{ secrets.SONATYPE_GPG_PRIVATE_KEY }}
gpg-passphrase: SONATYPE_GPG_PASSPHRASE
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v1
- with:
- registry: ghcr.io
- username: ${{ secrets.GIT_USERNAME }}
- password: ${{ secrets.GIT_PACKAGE_TOKEN }}
- name: Set Maven Project Version
shell: bash
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8069a29..f380e2c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -37,12 +37,6 @@ jobs:
server-password: SONATYPE_PASSWORD
gpg-private-key: ${{ secrets.SONATYPE_GPG_PRIVATE_KEY }}
gpg-passphrase: SONATYPE_GPG_PASSPHRASE
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v1
- with:
- registry: ghcr.io
- username: ${{ secrets.GIT_USERNAME }}
- password: ${{ secrets.GIT_PACKAGE_TOKEN }}
- name: Set Maven Project Version
id: set_maven_project_version
shell: bash
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index 2056017..061ea3c 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -1,17 +1,20 @@
-# Oracle GraalVM Java 8 Base Container
-ARG FROM=ghcr.io/graalvm/graalvm-ce:java11-21.3.0
-FROM ${FROM}
+# GraalVM Community Edition Base Container
+ARG FROM_VERSION=java11-21.3.0
+FROM ghcr.io/graalvm/graalvm-ce:${FROM_VERSION}
# Install native-image tool
RUN gu install --no-progress native-image
# Install musl libc
RUN curl -L -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
- && tar -xvf x86_64-linux-musl-native.tgz -C /usr/local/bin \
- && export CC=/usr/local/bin/x86_64-linux-musl-native/bin/gcc \
- && curl -kL -o zlib-1.2.11.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
- && tar -xvf zlib-1.2.11.tar.gz \
+ && tar -xvf x86_64-linux-musl-native.tgz -C /opt \
+ && export CC=/opt/x86_64-linux-musl-native/bin/gcc \
+ && curl -kL -o zlib.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
+ && tar -xvf zlib.tar.gz \
&& cd zlib-1.2.11 \
- && ./configure --prefix=/usr/local/bin/x86_64-linux-musl-native --static \
+ && ./configure --prefix=/opt/x86_64-linux-musl-native --static \
&& make \
&& make install
+
+# Update PATH Environment Variable
+ENV PATH="$PATH:/opt/x86_64-linux-musl-native/bin"
diff --git a/distributions/scripts/build-and-push-docker-builders.sh b/distributions/scripts/build-and-push-docker-builders.sh
deleted file mode 100755
index 3bdf453..0000000
--- a/distributions/scripts/build-and-push-docker-builders.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-
-##############################################################################################################
-#
-# Push Docker Builders to Remote Registry
-#
-##############################################################################################################
-
-set -e
-
-ROOT_DIR="$( cd "$( dirname "$( dirname "$( dirname "${BASH_SOURCE[0]}" )")")" && pwd )"
-DOCKER_BUILDERS_DIR="$ROOT_DIR/distributions/docker-builders"
-
-# Variables
-DOCKER_ORG="optum/ci"
-REGISTRY="ghcr.io"
-
-# Login to Registry
-echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin $REGISTRY
-
-# Native Image
-docker build -t $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java11 -f "$DOCKER_BUILDERS_DIR/Dockerfile-nativeimage" --build-arg FROM=ghcr.io/graalvm/graalvm-ce:java11-21.3.0 .
-docker build -t $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java17 -f "$DOCKER_BUILDERS_DIR/Dockerfile-nativeimage" --build-arg FROM=ghcr.io/graalvm/graalvm-ce:java17-21.3.0 .
-
-# RPM Build
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:centos7 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=centos:7 .
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:centos8 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=centos:8 .
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora33 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:33 .
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora34 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:34 .
-docker build -t $REGISTRY/$DOCKER_ORG/rpmbuild:fedora35 -f "$DOCKER_BUILDERS_DIR/Dockerfile-rpmbuild" --build-arg FROM=fedora:35 .
-
-# Push All Builders to Remote Registry
-docker push $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java11
-docker push $REGISTRY/$DOCKER_ORG/nativeimage:graalvm-ce-21.3.0-java17
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:centos7
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:centos8
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora33
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora34
-docker push $REGISTRY/$DOCKER_ORG/rpmbuild:fedora35
-
-# Log out of registry
-docker logout $REGISTRY
\ No newline at end of file
From 35bfe1b299fe6971b63eb697a6a8d18149e43567 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 17:51:44 -0500
Subject: [PATCH 17/31] remote-repository: Push docker builders
---
.github/workflows/build-and-push-docker-builders.yml | 7 -------
1 file changed, 7 deletions(-)
diff --git a/.github/workflows/build-and-push-docker-builders.yml b/.github/workflows/build-and-push-docker-builders.yml
index ca8510d..4c231b6 100644
--- a/.github/workflows/build-and-push-docker-builders.yml
+++ b/.github/workflows/build-and-push-docker-builders.yml
@@ -36,7 +36,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-nativeimage
build-args: FROM_VERSION=java11-21.3.0
- push: false
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java11
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -47,7 +46,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-nativeimage
build-args: FROM_VERSION=java17-21.3.0
- push: false
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java17
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -58,7 +56,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=centos:7
- push: false
tags: ghcr.io/optum/ci/rpmbuild:centos7
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -69,7 +66,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=centos:8
- push: false
tags: ghcr.io/optum/ci/rpmbuild:centos8
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -80,7 +76,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:33
- push: false
tags: ghcr.io/optum/ci/rpmbuild:fedora33
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -91,7 +86,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:34
- push: false
tags: ghcr.io/optum/ci/rpmbuild:fedora34
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
@@ -102,7 +96,6 @@ jobs:
context: .
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:35
- push: false
tags: ghcr.io/optum/ci/rpmbuild:fedora35
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
From 495043342b01189f1bc0499b5738c135b449fc75 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 17:58:25 -0500
Subject: [PATCH 18/31] remote-repository: Push docker builders
---
.github/workflows/build-and-push-docker-builders.yml | 10 +++++++++-
distributions/docker-builders/Dockerfile-nativeimage | 8 ++++----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/build-and-push-docker-builders.yml b/.github/workflows/build-and-push-docker-builders.yml
index 4c231b6..8a62a1a 100644
--- a/.github/workflows/build-and-push-docker-builders.yml
+++ b/.github/workflows/build-and-push-docker-builders.yml
@@ -10,7 +10,8 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - name: Git Checkout
+ uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.ref }}
- name: Set up Docker Buildx
@@ -37,6 +38,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-nativeimage
build-args: FROM_VERSION=java11-21.3.0
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java11
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push graalvm-ce-21.3.0-java17
@@ -47,6 +49,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-nativeimage
build-args: FROM_VERSION=java17-21.3.0
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java17
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild centos7
@@ -57,6 +60,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=centos:7
tags: ghcr.io/optum/ci/rpmbuild:centos7
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild centos8
@@ -67,6 +71,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=centos:8
tags: ghcr.io/optum/ci/rpmbuild:centos8
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora33
@@ -77,6 +82,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:33
tags: ghcr.io/optum/ci/rpmbuild:fedora33
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora34
@@ -87,6 +93,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:34
tags: ghcr.io/optum/ci/rpmbuild:fedora34
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora35
@@ -97,6 +104,7 @@ jobs:
file: distributions/docker-builders/Dockerfile-rpmbuild
build-args: FROM=fedora:35
tags: ghcr.io/optum/ci/rpmbuild:fedora35
+ push: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Relocate Docker Layer Cache
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index 061ea3c..3b2105e 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -6,11 +6,11 @@ FROM ghcr.io/graalvm/graalvm-ce:${FROM_VERSION}
RUN gu install --no-progress native-image
# Install musl libc
-RUN curl -L -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
- && tar -xvf x86_64-linux-musl-native.tgz -C /opt \
+RUN curl -ksL -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
+ && tar -xf x86_64-linux-musl-native.tgz -C /opt \
&& export CC=/opt/x86_64-linux-musl-native/bin/gcc \
- && curl -kL -o zlib.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
- && tar -xvf zlib.tar.gz \
+ && curl -ksL -o zlib.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
+ && tar -xf zlib.tar.gz \
&& cd zlib-1.2.11 \
&& ./configure --prefix=/opt/x86_64-linux-musl-native --static \
&& make \
From a0a57ac86b3f5389ff0d7f3a2a00eabf69033fe1 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 18:21:42 -0500
Subject: [PATCH 19/31] remote-repository: 0.7.0
---
bom/pom.xml | 2 +-
cli/pom.xml | 2 +-
core/pom.xml | 2 +-
distributions/debian/pom.xml | 2 +-
distributions/docker/pom.xml | 2 +-
distributions/linux/pom.xml | 2 +-
distributions/pom.xml | 2 +-
distributions/rpm/pom.xml | 2 +-
enforcer/core/pom.xml | 2 +-
enforcer/file/aot/pom.xml | 2 +-
enforcer/file/common/pom.xml | 2 +-
enforcer/file/core/pom.xml | 2 +-
enforcer/file/docker/pom.xml | 2 +-
enforcer/file/maven/pom.xml | 2 +-
enforcer/file/pom.xml | 2 +-
enforcer/file/registry/pom.xml | 2 +-
enforcer/pom.xml | 2 +-
exec/pom.xml | 2 +-
pom.xml | 2 +-
19 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/bom/pom.xml b/bom/pom.xml
index c18379b..febfdc6 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
sourcehawk-bom
diff --git a/cli/pom.xml b/cli/pom.xml
index 624debf..7ac24e7 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -8,7 +8,7 @@
sourcehawk
com.optum.sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
sourcehawk-cli
diff --git a/core/pom.xml b/core/pom.xml
index a840223..0d73a61 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/distributions/debian/pom.xml b/distributions/debian/pom.xml
index 16963e4..158df2d 100644
--- a/distributions/debian/pom.xml
+++ b/distributions/debian/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/distributions/docker/pom.xml b/distributions/docker/pom.xml
index 1a11871..2485517 100644
--- a/distributions/docker/pom.xml
+++ b/distributions/docker/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 855bc85..423b4a1 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-dist
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/distributions/pom.xml b/distributions/pom.xml
index e1a410e..ebae0b5 100644
--- a/distributions/pom.xml
+++ b/distributions/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/distributions/rpm/pom.xml b/distributions/rpm/pom.xml
index 6dfbb23..19e90da 100644
--- a/distributions/rpm/pom.xml
+++ b/distributions/rpm/pom.xml
@@ -8,7 +8,7 @@
sourcehawk-dist
com.optum.sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
sourcehawk-dist-rpm
diff --git a/enforcer/core/pom.xml b/enforcer/core/pom.xml
index 93e09a2..fb9c5d6 100644
--- a/enforcer/core/pom.xml
+++ b/enforcer/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/aot/pom.xml b/enforcer/file/aot/pom.xml
index 7c233bf..43086e6 100644
--- a/enforcer/file/aot/pom.xml
+++ b/enforcer/file/aot/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/common/pom.xml b/enforcer/file/common/pom.xml
index 8d0ef8a..8604ff5 100644
--- a/enforcer/file/common/pom.xml
+++ b/enforcer/file/common/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/core/pom.xml b/enforcer/file/core/pom.xml
index cd74cb7..96c8013 100644
--- a/enforcer/file/core/pom.xml
+++ b/enforcer/file/core/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/docker/pom.xml b/enforcer/file/docker/pom.xml
index 988a7bc..6ec6ae9 100644
--- a/enforcer/file/docker/pom.xml
+++ b/enforcer/file/docker/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/maven/pom.xml b/enforcer/file/maven/pom.xml
index 699b4cf..76dd2ef 100644
--- a/enforcer/file/maven/pom.xml
+++ b/enforcer/file/maven/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/pom.xml b/enforcer/file/pom.xml
index 1852619..bbb6251 100644
--- a/enforcer/file/pom.xml
+++ b/enforcer/file/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/file/registry/pom.xml b/enforcer/file/registry/pom.xml
index bf8c359..663031c 100644
--- a/enforcer/file/registry/pom.xml
+++ b/enforcer/file/registry/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk-enforcer-file
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/enforcer/pom.xml b/enforcer/pom.xml
index 6254ec3..ee974cc 100644
--- a/enforcer/pom.xml
+++ b/enforcer/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/exec/pom.xml b/exec/pom.xml
index 1033150..a7bc559 100644
--- a/exec/pom.xml
+++ b/exec/pom.xml
@@ -8,7 +8,7 @@
com.optum.sourcehawk
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
../pom.xml
diff --git a/pom.xml b/pom.xml
index ab8b605..0aae6ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
sourcehawk
- 0.6.1-SNAPSHOT
+ 0.7.0-SNAPSHOT
pom
Sourcehawk
From c61d4318872abf54f0e5ac649ab7142a16bac82a Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 18:33:27 -0500
Subject: [PATCH 20/31] remote-repository: Skip native image build for java 8
---
distributions/linux/pom.xml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 423b4a1..9adab8d 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -23,6 +23,7 @@
/home/${global.project.name}
${docker.workdir}/${global.project.name}
${project.build.directory}/${global.project.name}
+ false
true
@@ -57,6 +58,7 @@
copy-resources
+ ${native.image.build.skip}
${project.parent.parent.basedir}/gh-pages/manpages
@@ -82,6 +84,7 @@
copy-dependencies
+ ${native.image.build.skip}
com.optum.sourcehawk
sourcehawk-cli
native-image
@@ -95,6 +98,7 @@
copy
+ ${native.image.build.skip}
com.optum.sourcehawk
@@ -123,6 +127,7 @@
tag
+ ${native.image.build.skip}
${basedir}/native-image-builder/Dockerfile
${docker.image}
${project.version}
@@ -152,6 +157,7 @@
exec
+ ${native.image.build.skip}
../scripts/extract-file-from-docker-container.sh
${docker.image}:${project.version}
@@ -176,6 +182,7 @@
post-integration-test
+ ${native.image.build.skip}
${native.image}
@@ -259,6 +266,7 @@
exec
+ ${native.image.build.skip}
${native.image}
--version
@@ -272,6 +280,17 @@
+
+
+ native-image-build-java11
+
+ 8
+
+
+ true
+
+
+
native-image-build-java11
From e23b5f1167d1045379ec7c07f9568ca1084999f7 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 18:35:12 -0500
Subject: [PATCH 21/31] remote-repository: Skip native image build for java 8
---
distributions/linux/pom.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 9adab8d..d6fb4ee 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -282,7 +282,7 @@
- native-image-build-java11
+ java8
8
@@ -293,7 +293,7 @@
- native-image-build-java11
+ java11
11
@@ -304,7 +304,7 @@
- native-image-build-java17
+ java17
17
From e611c42be46d53d76e9ee863f45259aa11b85eaf Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 18:51:41 -0500
Subject: [PATCH 22/31] remote-repository: Fix java8 build and workflow
dependencies
---
.github/workflows/maven-ci.yml | 4 ++--
.github/workflows/release.yml | 20 +++++++++----------
cli/scripts/update-picocli.sh | 2 +-
cli/src/main/java/picocli/CommandLine.java | 1 +
.../docker-builders/Dockerfile-nativeimage | 2 +-
distributions/linux/pom.xml | 4 +++-
6 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index 1e92448..da5ac95 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -116,7 +116,7 @@ jobs:
report_paths: '**/target/surefire-reports/TEST-*.xml,**/target/failsafe-reports/TEST-*.xml'
build-mac-native-image:
runs-on: macos-latest
- needs: build
+ needs: build-11
steps:
- uses: actions/download-artifact@v2
with:
@@ -168,7 +168,7 @@ jobs:
run: ./sourcehawk help
build-windows-native-image:
runs-on: windows-latest
- needs: build
+ needs: build-11
steps:
- uses: actions/download-artifact@v2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f380e2c..b94e170 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -237,7 +237,7 @@ jobs:
path: cli/target/*-native-image.jar
build-mac-native-image:
runs-on: macos-latest
- needs: build
+ needs: build-11
steps:
- uses: actions/download-artifact@v2
with:
@@ -284,9 +284,9 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk
- asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-darwin-x86_64
+ asset_name: sourcehawk-${{ needs.build-11.outputs.RELEASE_VERSION }}-darwin-x86_64
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Mac Homebrew Tap Formula Archive
id: upload_homebrew_tap_formula_archive
@@ -296,25 +296,25 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk-homebrew-tap-formula.tar.gz
- asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
+ asset_name: sourcehawk-${{ needs.build-11.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
asset_content_type: application/octet-stream
- name: Update Optum Homebrew Tap Formula
uses: mislav/bump-homebrew-formula-action@v1.10
continue-on-error: true
with:
formula-name: sourcehawk
- tag-name: ${{ needs.build.outputs.RELEASE_VERSION }}
+ tag-name: ${{ needs.build-11.outputs.RELEASE_VERSION }}
homebrew-tap: optum/homebrew-tap
base-branch: main
download-url: ${{ steps.upload_homebrew_tap_formula_archive.outputs.browser_download_url }}
- commit-message: Updating sourcehawk formula to latest release version ${{ needs.build.outputs.RELEASE_VERSION }}
+ commit-message: Updating sourcehawk formula to latest release version ${{ needs.build-11.outputs.RELEASE_VERSION }}
env:
COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }}
build-windows-native-image:
runs-on: windows-latest
- needs: [build, build-java11]
+ needs: build-java11
steps:
- uses: actions/download-artifact@v2
with:
@@ -344,7 +344,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: sourcehawk.exe
- asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-windows-x86_64.exe
+ asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-windows-x86_64.exe
asset_content_type: application/octet-stream
diff --git a/cli/scripts/update-picocli.sh b/cli/scripts/update-picocli.sh
index 3d35f7d..84011f5 100755
--- a/cli/scripts/update-picocli.sh
+++ b/cli/scripts/update-picocli.sh
@@ -28,7 +28,7 @@ curl -ksf "$LICENSE_URL" > "$LICENSE_FILE_PATH"
curl -ksf "$SOURCE_URL" > "$SOURCE_FILE_PATH"
# Add some warning suppression to the java source file
-sed -i.bak -e 's/public\sclass\sCommandLine/@SuppressWarnings({"rawtypes", "deprecation" })\npublic class CommandLine/g' \
+sed -i.bak -e 's/public class CommandLine/@SuppressWarnings({"rawtypes", "deprecation" })\npublic class CommandLine/g' \
-e 's/TODO/TIDO/g' "$SOURCE_FILE_PATH" \
&& rm -rf "$SOURCE_FILE_PATH.bak"
diff --git a/cli/src/main/java/picocli/CommandLine.java b/cli/src/main/java/picocli/CommandLine.java
index a0f8454..07a29c9 100644
--- a/cli/src/main/java/picocli/CommandLine.java
+++ b/cli/src/main/java/picocli/CommandLine.java
@@ -142,6 +142,7 @@
*
*
*/
+@SuppressWarnings({"rawtypes", "deprecation" })
public class CommandLine {
/** This is picocli version {@value}. */
diff --git a/distributions/docker-builders/Dockerfile-nativeimage b/distributions/docker-builders/Dockerfile-nativeimage
index 3b2105e..b0c52ca 100644
--- a/distributions/docker-builders/Dockerfile-nativeimage
+++ b/distributions/docker-builders/Dockerfile-nativeimage
@@ -6,7 +6,7 @@ FROM ghcr.io/graalvm/graalvm-ce:${FROM_VERSION}
RUN gu install --no-progress native-image
# Install musl libc
-RUN curl -ksL -o x86_64-linux-musl-native.tgz http://musl.cc/x86_64-linux-musl-native.tgz \
+RUN curl -ksL -o x86_64-linux-musl-native.tgz https://more.musl.cc/10.2.1/x86_64-linux-musl/x86_64-linux-musl-native.tgz \
&& tar -xf x86_64-linux-musl-native.tgz -C /opt \
&& export CC=/opt/x86_64-linux-musl-native/bin/gcc \
&& curl -ksL -o zlib.tar.gz https://zlib.net/zlib-1.2.11.tar.gz \
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index d6fb4ee..effa34d 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -23,7 +23,7 @@
/home/${global.project.name}
${docker.workdir}/${global.project.name}
${project.build.directory}/${global.project.name}
- false
+
true
@@ -299,6 +299,7 @@
21.3.0-java11
+ false
@@ -310,6 +311,7 @@
21.3.0-java17
+ false
From 27f1624e5cb5fa0cfb2667c762eb600a547d6568 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 19:11:07 -0500
Subject: [PATCH 23/31] remote-repository: Fix needs syntax
---
.github/workflows/maven-ci.yml | 5 +++--
.github/workflows/release.yml | 16 ++++++++--------
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index da5ac95..aa5dbaa 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -114,9 +114,10 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
report_paths: '**/target/surefire-reports/TEST-*.xml,**/target/failsafe-reports/TEST-*.xml'
+ check_name: Test Report - Java ${{ matrix.java }}
build-mac-native-image:
runs-on: macos-latest
- needs: build-11
+ needs: build
steps:
- uses: actions/download-artifact@v2
with:
@@ -168,7 +169,7 @@ jobs:
run: ./sourcehawk help
build-windows-native-image:
runs-on: windows-latest
- needs: build-11
+ needs: build
steps:
- uses: actions/download-artifact@v2
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b94e170..1af3a39 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -237,7 +237,7 @@ jobs:
path: cli/target/*-native-image.jar
build-mac-native-image:
runs-on: macos-latest
- needs: build-11
+ needs: build-java11
steps:
- uses: actions/download-artifact@v2
with:
@@ -284,9 +284,9 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk
- asset_name: sourcehawk-${{ needs.build-11.outputs.RELEASE_VERSION }}-darwin-x86_64
+ asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-darwin-x86_64
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Mac Homebrew Tap Formula Archive
id: upload_homebrew_tap_formula_archive
@@ -296,20 +296,20 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk-homebrew-tap-formula.tar.gz
- asset_name: sourcehawk-${{ needs.build-11.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
+ asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
asset_content_type: application/octet-stream
- name: Update Optum Homebrew Tap Formula
uses: mislav/bump-homebrew-formula-action@v1.10
continue-on-error: true
with:
formula-name: sourcehawk
- tag-name: ${{ needs.build-11.outputs.RELEASE_VERSION }}
+ tag-name: ${{ needs.build-java11.outputs.RELEASE_VERSION }}
homebrew-tap: optum/homebrew-tap
base-branch: main
download-url: ${{ steps.upload_homebrew_tap_formula_archive.outputs.browser_download_url }}
- commit-message: Updating sourcehawk formula to latest release version ${{ needs.build-11.outputs.RELEASE_VERSION }}
+ commit-message: Updating sourcehawk formula to latest release version ${{ needs.build-java11.outputs.RELEASE_VERSION }}
env:
COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }}
build-windows-native-image:
@@ -344,7 +344,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: sourcehawk.exe
asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-windows-x86_64.exe
asset_content_type: application/octet-stream
From 1758b928ae03a943f7eaf94f182f3b2ea5eae13a Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 19:21:58 -0500
Subject: [PATCH 24/31] remote-repository: 1.8 reference to identigy java 8 in
mvn profile
---
distributions/linux/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index effa34d..3479727 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -284,7 +284,7 @@
java8
- 8
+ 1.8
true
From 05be46b7ac134bcad13ea3dc67288d181b395e33 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 19:26:43 -0500
Subject: [PATCH 25/31] remote-repository: Skip failsafe integration tests for
java8
---
.github/workflows/maven-ci.yml | 2 +-
distributions/linux/pom.xml | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index aa5dbaa..e061736 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -114,7 +114,7 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
report_paths: '**/target/surefire-reports/TEST-*.xml,**/target/failsafe-reports/TEST-*.xml'
- check_name: Test Report - Java ${{ matrix.java }}
+ check_name: Test Report (${{ matrix.java }})
build-mac-native-image:
runs-on: macos-latest
needs: build
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 3479727..63fff97 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -289,6 +289,17 @@
true
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+ true
+
+
+
+
From 8b6d5c694fe44724ebefadadd6d8661d779e709b Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 19:55:23 -0500
Subject: [PATCH 26/31] remote-repository: Only build dist when not java 8
---
.github/workflows/release.yml | 108 ++++++++++++++++------------------
distributions/linux/pom.xml | 32 ----------
distributions/pom.xml | 7 ---
pom.xml | 1 +
4 files changed, 52 insertions(+), 96 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1af3a39..a5ea1fd 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -56,23 +56,45 @@ jobs:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SONATYPE_GPG_PASSPHRASE: ${{ secrets.SONATYPE_GPG_PASSPHRASE }}
+ build-java11:
+ runs-on: ubuntu-latest
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ ref: ${{ github.event.inputs.ref }}
+ - name: Setup Java and Maven
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - name: Set Maven Project Version
+ shell: bash
+ run: |
+ RELEASE_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout | tail -1 | tr -d '\r\n')
+ [[ "$RELEASE_VERSION" == *"-SNAPSHOT" ]] && RELEASE_VERSION="${RELEASE_VERSION%"-SNAPSHOT"}" && ./mvnw --batch-mode versions:set -D removeSnapshot || true
+ [[ "$(git tag -l $RELEASE_VERSION)" == "$RELEASE_VERSION" ]] && echo "Tag $RELEASE_VERSION already exists" && exit 1
+ echo ::set-output name=RELEASE_VERSION::$RELEASE_VERSION
+ - name: Build Maven Project
+ if: success()
+ run: ./mvnw --batch-mode install -D ci.build -D ci.release
- name: Archive Native Image JAR
if: success()
uses: actions/upload-artifact@v2
with:
- name: native-image
+ name: native-image-11
path: cli/target/*-native-image.jar
- name: Archive Bash Completion Script
if: success()
uses: actions/upload-artifact@v2
with:
- name: bash-completion-script
+ name: bash-completion-script-11
path: cli/target/sourcehawk-bash-completion.sh
- name: Archive Manpages
if: success()
uses: actions/upload-artifact@v2
with:
- name: manpages
+ name: manpages-11
path: gh-pages/manpages/sourcehawk*.1
- name: Aggregate Coverage Reports
id: aggregate_coverage_reports
@@ -106,10 +128,19 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ format('v{0}', steps.set_maven_project_version.outputs.RELEASE_VERSION) }}
- release_name: ${{ format('{0} {1}', github.event.repository.name, steps.set_maven_project_version.outputs.RELEASE_VERSION) }}
+ release_name: ${{ format('{0} {1}', github.event.repository.name, needs.build.outputs.RELEASE_VERSION) }}
body_path: CHANGELOG.md
draft: ${{ github.event.inputs.draft }}
prerelease: ${{ github.event.inputs.prerelease }}
+ - name: Publish Github Pages
+ if: success()
+ continue-on-error: true
+ uses: jamesives/github-pages-deploy-action@3.7.1
+ with:
+ COMMIT_MESSAGE: ${{ format('Publishing github pages for release version {0}', needs.build.outputs.RELEASE_VERSION) }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BRANCH: gh-pages
+ FOLDER: gh-pages
- name: Upload Sourcehawk Linux Executable
if: success()
continue-on-error: true
@@ -119,7 +150,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/linux/target/sourcehawk
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-linux-x86_64
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-linux-x86_64
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Debian Buster Package
if: success()
@@ -130,7 +161,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/debian/target/sourcehawk-debian-buster.deb
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-debian-buster-amd64.deb
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-debian-buster-amd64.deb
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Ubuntu Focal Package
if: success()
@@ -141,7 +172,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/debian/target/sourcehawk-ubuntu-focal.deb
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-ubuntu-focal-amd64.deb
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-ubuntu-focal-amd64.deb
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Centos 7 RPM Package
if: success()
@@ -152,7 +183,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/rpm/target/sourcehawk-centos-7.rpm
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.el7.x86_64.rpm
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-1.el7.x86_64.rpm
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Centos 8 RPM Package
if: success()
@@ -163,7 +194,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/rpm/target/sourcehawk-centos-8.rpm
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.el8.x86_64.rpm
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-1.el8.x86_64.rpm
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Fedora 33 RPM Package
if: success()
@@ -174,7 +205,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/rpm/target/sourcehawk-fedora-33.rpm
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.fc33.x86_64.rpm
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-1.fc33.x86_64.rpm
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Fedora 34 RPM Package
if: success()
@@ -185,7 +216,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/rpm/target/sourcehawk-fedora-34.rpm
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.fc34.x86_64.rpm
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-1.fc34.x86_64.rpm
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Fedora 35 RPM Package
if: success()
@@ -196,45 +227,8 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./distributions/rpm/target/sourcehawk-fedora-35.rpm
- asset_name: sourcehawk-${{ steps.set_maven_project_version.outputs.RELEASE_VERSION }}-1.fc35.x86_64.rpm
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-1.fc35.x86_64.rpm
asset_content_type: application/octet-stream
- - name: Publish Github Pages
- if: success()
- continue-on-error: true
- uses: jamesives/github-pages-deploy-action@3.7.1
- with:
- COMMIT_MESSAGE: ${{ format('Publishing github pages for release version {0}', steps.set_maven_project_version.outputs.RELEASE_VERSION) }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- BRANCH: gh-pages
- FOLDER: gh-pages
- build-java11:
- runs-on: ubuntu-latest
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- steps:
- - uses: actions/checkout@v2
- with:
- ref: ${{ github.event.inputs.ref }}
- - name: Setup Java and Maven
- uses: actions/setup-java@v1
- with:
- java-version: 11
- - name: Set Maven Project Version
- shell: bash
- run: |
- RELEASE_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout | tail -1 | tr -d '\r\n')
- [[ "$RELEASE_VERSION" == *"-SNAPSHOT" ]] && RELEASE_VERSION="${RELEASE_VERSION%"-SNAPSHOT"}" && ./mvnw --batch-mode versions:set -D removeSnapshot || true
- [[ "$(git tag -l $RELEASE_VERSION)" == "$RELEASE_VERSION" ]] && echo "Tag $RELEASE_VERSION already exists" && exit 1
- echo ::set-output name=RELEASE_VERSION::$RELEASE_VERSION
- - name: Build Maven Project
- if: success()
- run: ./mvnw --batch-mode install -D ci.build -D ci.release
- - name: Archive Native Image JAR
- if: success()
- uses: actions/upload-artifact@v2
- with:
- name: native-image-java11
- path: cli/target/*-native-image.jar
build-mac-native-image:
runs-on: macos-latest
needs: build-java11
@@ -284,9 +278,9 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk
- asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-darwin-x86_64
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-darwin-x86_64
asset_content_type: application/octet-stream
- name: Upload Sourcehawk Mac Homebrew Tap Formula Archive
id: upload_homebrew_tap_formula_archive
@@ -296,20 +290,20 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: build/sourcehawk-homebrew-tap-formula.tar.gz
- asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-darwin-x86_64.tar.gz
asset_content_type: application/octet-stream
- name: Update Optum Homebrew Tap Formula
uses: mislav/bump-homebrew-formula-action@v1.10
continue-on-error: true
with:
formula-name: sourcehawk
- tag-name: ${{ needs.build-java11.outputs.RELEASE_VERSION }}
+ tag-name: ${{ needs.build.outputs.RELEASE_VERSION }}
homebrew-tap: optum/homebrew-tap
base-branch: main
download-url: ${{ steps.upload_homebrew_tap_formula_archive.outputs.browser_download_url }}
- commit-message: Updating sourcehawk formula to latest release version ${{ needs.build-java11.outputs.RELEASE_VERSION }}
+ commit-message: Updating sourcehawk formula to latest release version ${{ needs.build.outputs.RELEASE_VERSION }}
env:
COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }}
build-windows-native-image:
@@ -344,7 +338,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- upload_url: ${{ needs.build-java11.outputs.RELEASE_ASSET_UPLOAD_URL }}
+ upload_url: ${{ needs.build.outputs.RELEASE_ASSET_UPLOAD_URL }}
asset_path: sourcehawk.exe
- asset_name: sourcehawk-${{ needs.build-java11.outputs.RELEASE_VERSION }}-windows-x86_64.exe
+ asset_name: sourcehawk-${{ needs.build.outputs.RELEASE_VERSION }}-windows-x86_64.exe
asset_content_type: application/octet-stream
diff --git a/distributions/linux/pom.xml b/distributions/linux/pom.xml
index 63fff97..7a7159d 100644
--- a/distributions/linux/pom.xml
+++ b/distributions/linux/pom.xml
@@ -23,7 +23,6 @@
/home/${global.project.name}
${docker.workdir}/${global.project.name}
${project.build.directory}/${global.project.name}
-
true
@@ -58,7 +57,6 @@
copy-resources
- ${native.image.build.skip}
${project.parent.parent.basedir}/gh-pages/manpages
@@ -84,7 +82,6 @@
copy-dependencies
- ${native.image.build.skip}
com.optum.sourcehawk
sourcehawk-cli
native-image
@@ -98,7 +95,6 @@
copy
- ${native.image.build.skip}
com.optum.sourcehawk
@@ -127,7 +123,6 @@
tag
- ${native.image.build.skip}
${basedir}/native-image-builder/Dockerfile
${docker.image}
${project.version}
@@ -157,7 +152,6 @@
exec
- ${native.image.build.skip}
../scripts/extract-file-from-docker-container.sh
${docker.image}:${project.version}
@@ -182,7 +176,6 @@
post-integration-test
- ${native.image.build.skip}
${native.image}
@@ -266,7 +259,6 @@
exec
- ${native.image.build.skip}
${native.image}
--version
@@ -280,28 +272,6 @@
-
-
- java8
-
- 1.8
-
-
- true
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
-
- true
-
-
-
-
-
-
java11
@@ -310,7 +280,6 @@
21.3.0-java11
- false
@@ -322,7 +291,6 @@
21.3.0-java17
- false
diff --git a/distributions/pom.xml b/distributions/pom.xml
index ebae0b5..a488bba 100644
--- a/distributions/pom.xml
+++ b/distributions/pom.xml
@@ -69,11 +69,4 @@
-
- linux
- debian
- rpm
- docker
-
-
diff --git a/pom.xml b/pom.xml
index 0aae6ea..ffedf93 100644
--- a/pom.xml
+++ b/pom.xml
@@ -213,6 +213,7 @@
distributions-build
+ !1.8
ci.build
From df01c7f607bd88e35dc53f982a4ba9f86ce747e7 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 20:08:50 -0500
Subject: [PATCH 27/31] remote-repository: Fix dist pom
---
distributions/pom.xml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/distributions/pom.xml b/distributions/pom.xml
index a488bba..ebae0b5 100644
--- a/distributions/pom.xml
+++ b/distributions/pom.xml
@@ -69,4 +69,11 @@
+
+ linux
+ debian
+ rpm
+ docker
+
+
From 9597d7620da54b44a231257069f51bbee2ef4a26 Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 20:30:23 -0500
Subject: [PATCH 28/31] remote-repository: Don't cache docker builders
---
.../build-and-push-docker-builders.yml | 25 -------------------
1 file changed, 25 deletions(-)
diff --git a/.github/workflows/build-and-push-docker-builders.yml b/.github/workflows/build-and-push-docker-builders.yml
index 8a62a1a..c9b2543 100644
--- a/.github/workflows/build-and-push-docker-builders.yml
+++ b/.github/workflows/build-and-push-docker-builders.yml
@@ -17,13 +17,6 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- - name: Cache Docker Layers
- uses: actions/cache@v2
- with:
- path: /tmp/.buildx-cache
- key: ${{ runner.os }}-buildx-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-buildx-
- name: Login to Github Container Registry
uses: docker/login-action@v1
with:
@@ -39,8 +32,6 @@ jobs:
build-args: FROM_VERSION=java11-21.3.0
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java11
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push graalvm-ce-21.3.0-java17
uses: docker/build-push-action@v2
with:
@@ -50,8 +41,6 @@ jobs:
build-args: FROM_VERSION=java17-21.3.0
tags: ghcr.io/optum/ci/nativeimage:graalvm-ce-21.3.0-java17
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild centos7
uses: docker/build-push-action@v2
with:
@@ -61,8 +50,6 @@ jobs:
build-args: FROM=centos:7
tags: ghcr.io/optum/ci/rpmbuild:centos7
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild centos8
uses: docker/build-push-action@v2
with:
@@ -72,8 +59,6 @@ jobs:
build-args: FROM=centos:8
tags: ghcr.io/optum/ci/rpmbuild:centos8
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora33
uses: docker/build-push-action@v2
with:
@@ -83,8 +68,6 @@ jobs:
build-args: FROM=fedora:33
tags: ghcr.io/optum/ci/rpmbuild:fedora33
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora34
uses: docker/build-push-action@v2
with:
@@ -94,8 +77,6 @@ jobs:
build-args: FROM=fedora:34
tags: ghcr.io/optum/ci/rpmbuild:fedora34
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- name: Build and Push rpmbuild fedora35
uses: docker/build-push-action@v2
with:
@@ -105,9 +86,3 @@ jobs:
build-args: FROM=fedora:35
tags: ghcr.io/optum/ci/rpmbuild:fedora35
push: true
- cache-from: type=local,src=/tmp/.buildx-cache
- cache-to: type=local,dest=/tmp/.buildx-cache-new
- - name: Relocate Docker Layer Cache
- run: |
- rm -rf /tmp/.buildx-cache
- mv /tmp/.buildx-cache-new /tmp/.buildx-cache
From 873a4cb2117917d355b72f1ec670fdfea6b11b1d Mon Sep 17 00:00:00 2001
From: Brian Wyka
Date: Sat, 22 Jan 2022 21:21:47 -0500
Subject: [PATCH 29/31] remote-repository: Only build dist for java 11, use
20.3.0 for windows native image
---
.github/workflows/maven-ci.yml | 11 ++++++-----
.github/workflows/release.yml | 2 +-
pom.xml | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index e061736..1f25c4e 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -79,26 +79,26 @@ jobs:
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SONATYPE_GPG_PASSPHRASE: ${{ secrets.SONATYPE_GPG_PASSPHRASE }}
- name: Archive Native Image JAR
- if: success()
+ if: success() && (matrix.java == '11')
uses: actions/upload-artifact@v2
with:
name: native-image-${{ matrix.java }}
path: cli/target/*-native-image.jar
- name: Archive Bash Completion Script
- if: success()
+ if: success() && (matrix.java == '11')
uses: actions/upload-artifact@v2
with:
name: bash-completion-script-${{ matrix.java }}
path: cli/target/sourcehawk-bash-completion.sh
- name: Archive Manpages
- if: success()
+ if: success() && (matrix.java == '11')
uses: actions/upload-artifact@v2
with:
name: manpages-${{ matrix.java }}
path: gh-pages/manpages/sourcehawk*.1
- name: Aggregate Coverage Reports
id: aggregate_coverage_reports
- if: success()
+ if: success() && (matrix.java == '11')
run: echo ::set-output name=JACOCO_XML_REPORT_PATHS::$(find . -name "jacoco.xml" -printf '%P\n' | tr '\r\n' ',')
- name: Analyze with SonarCloud
if: success() && (github.event_name == 'push' && matrix.java == '11')
@@ -170,6 +170,7 @@ jobs:
build-windows-native-image:
runs-on: windows-latest
needs: build
+ continue-on-error: true
steps:
- uses: actions/download-artifact@v2
with:
@@ -181,7 +182,7 @@ jobs:
- name: Setup GraalVM
uses: graalvm/setup-graalvm@v1
with:
- version: '21.3.0'
+ version: '20.3.0'
java-version: '11'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a5ea1fd..9ffa6ea 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -320,7 +320,7 @@ jobs:
- name: Setup GraalVM
uses: graalvm/setup-graalvm@v1
with:
- version: '21.3.0'
+ version: '20.3.0'
java-version: '11'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/pom.xml b/pom.xml
index ffedf93..39b2b17 100644
--- a/pom.xml
+++ b/pom.xml
@@ -213,7 +213,7 @@
distributions-build
- !1.8
+ 11
ci.build
From e1c89f230724b88ef2785ab4274b997e928fcdc3 Mon Sep 17 00:00:00 2001
From: Brian Wyka <46069296+brianwyka@users.noreply.github.com>
Date: Sat, 22 Jan 2022 23:35:55 -0500
Subject: [PATCH 30/31] Revert to Test Report
---
.github/workflows/maven-ci.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml
index 1f25c4e..c1a05b7 100644
--- a/.github/workflows/maven-ci.yml
+++ b/.github/workflows/maven-ci.yml
@@ -114,7 +114,6 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
report_paths: '**/target/surefire-reports/TEST-*.xml,**/target/failsafe-reports/TEST-*.xml'
- check_name: Test Report (${{ matrix.java }})
build-mac-native-image:
runs-on: macos-latest
needs: build
@@ -199,4 +198,4 @@ jobs:
- name: Smoke Test
if: success()
shell: cmd
- run: sourcehawk.exe help
\ No newline at end of file
+ run: sourcehawk.exe help
From 9b67c4a2bc15ffc070e73f5bf23fd94cc34cebea Mon Sep 17 00:00:00 2001
From: Christian Oestreich
Date: Sun, 23 Jan 2022 19:38:26 -0600
Subject: [PATCH 31/31] WIP: adding more enforcers for NOT conditions
---
.../file/common/AbstractContains.java | 37 ++
.../enforcer/file/common/AbstractContent.java | 73 ++++
.../enforcer/file/common/Contains.java | 25 +-
.../enforcer/file/common/ContentEquals.java | 60 +--
.../file/common/ContentNotEquals.java | 75 ++++
.../enforcer/file/common/NotContains.java | 34 ++
.../enforcer/file/common/NotContainsLine.java | 50 +++
.../file/common/Sha256ChecksumNotEquals.java | 65 +++
.../enforcer/file/json/AbstractJsonValue.java | 240 +++++++++++
.../enforcer/file/json/JsonValueEquals.java | 220 +---------
.../file/json/JsonValueNotEquals.java | 76 ++++
.../file/yaml/YamlValueNotEquals.java | 69 +++
.../file/common/ContentNotEqualsSpec.groovy | 80 ++++
.../file/common/NotContainsLineSpec.groovy | 66 +++
.../file/common/NotContainsSpec.groovy | 67 +++
.../common/Sha256ChecksumNotEqualsSpec.groovy | 54 +++
.../file/json/JsonValueNotEqualsSpec.groovy | 401 ++++++++++++++++++
.../file/yaml/YamlValueNotEqualsSpec.groovy | 127 ++++++
18 files changed, 1536 insertions(+), 283 deletions(-)
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContains.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContent.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentNotEquals.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContains.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContainsLine.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEquals.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/AbstractJsonValue.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEquals.java
create mode 100644 enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEquals.java
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/ContentNotEqualsSpec.groovy
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsLineSpec.groovy
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsSpec.groovy
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEqualsSpec.groovy
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEqualsSpec.groovy
create mode 100644 enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEqualsSpec.groovy
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContains.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContains.java
new file mode 100644
index 0000000..f1a8d72
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContains.java
@@ -0,0 +1,37 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An abstract class for contains to allow different types of operations
+ *
+ * @author Christian Oestreich
+ */
+public abstract class AbstractContains extends AbstractFileEnforcer {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
+ val actualFileContent = toString(actualFileInputStream);
+ if (passes(actualFileContent)) {
+ return EnforcerResult.failed(String.format(getMessageTemplate(), getExpectedSubstring()));
+ }
+ return EnforcerResult.passed();
+ }
+
+ protected boolean passes(String actualFileContent) {
+ return !actualFileContent.contains(getExpectedSubstring());
+ }
+
+ protected abstract String getExpectedSubstring();
+
+ protected abstract String getMessageTemplate();
+}
\ No newline at end of file
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContent.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContent.java
new file mode 100644
index 0000000..ce0dbf0
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/AbstractContent.java
@@ -0,0 +1,73 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.*;
+import java.net.URL;
+
+public abstract class AbstractContent extends AbstractFileEnforcer {
+
+ /**
+ * The expected file contents
+ */
+ protected abstract String getExpectedFileContents();
+
+ /**
+ * The URL to use for comparison
+ */
+ protected abstract URL getExpectedUrl();
+
+ protected abstract String getDefaultMessage();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
+ try (val expectedFileContentsReader = new BufferedReader(resolveReader());
+ val actualFileContentsReader = new BufferedReader(new InputStreamReader(actualFileInputStream))) {
+ if (equals(expectedFileContentsReader, actualFileContentsReader)) {
+ return EnforcerResult.passed();
+ }
+ }
+ return EnforcerResult.failed(getDefaultMessage());
+ }
+
+ /**
+ * Resolve the appropriate reader to be used
+ *
+ * @return the reader of the expected file contents
+ * @throws IOException if any error occurs opening file contents from URL
+ */
+ private Reader resolveReader() throws IOException {
+ if (getExpectedUrl() != null) {
+ return new InputStreamReader(getExpectedUrl().openStream());
+ } else {
+ return new StringReader(getExpectedFileContents());
+ }
+ }
+
+ /**
+ * Determine if the two buffered readers have identical contents
+ *
+ * @param expectedReader the expected buffered reader
+ * @param actualReader the actual buffered reader
+ * @return true if content is identical, false otherwise
+ * @throws IOException if any error occurs reading files
+ */
+ protected boolean equals(final BufferedReader expectedReader, final BufferedReader actualReader) throws IOException {
+ if (expectedReader == actualReader) {
+ return true;
+ }
+ String line1 = expectedReader.readLine();
+ String line2 = actualReader.readLine();
+ while (line1 != null && line1.equals(line2)) {
+ line1 = expectedReader.readLine();
+ line2 = actualReader.readLine();
+ }
+ return line1 == null && line2 == null;
+ }
+}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Contains.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Contains.java
index 55e2d61..188b0f5 100644
--- a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Contains.java
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Contains.java
@@ -1,25 +1,21 @@
package com.optum.sourcehawk.enforcer.file.common;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.optum.sourcehawk.enforcer.EnforcerResult;
-import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
import lombok.AllArgsConstructor;
import lombok.Builder;
-import lombok.NonNull;
-import lombok.val;
-
-import java.io.IOException;
-import java.io.InputStream;
+import lombok.Getter;
/**
* An enforcer which is responsible for enforcing that file contains a string
*
* @author Brian Wyka
+ * @author Christian Oestreich
*/
@Builder(builderClassName = "Builder")
@JsonDeserialize(builder = Contains.Builder.class)
@AllArgsConstructor(staticName = "substring")
-public class Contains extends AbstractFileEnforcer {
+@Getter
+public class Contains extends AbstractContains {
private static final String MESSAGE_TEMPLATE = "File does not contain the sub string [%s]";
@@ -28,15 +24,12 @@ public class Contains extends AbstractFileEnforcer {
*/
protected final String expectedSubstring;
+ protected boolean passes(String actualFileContent) {
+ return !actualFileContent.contains(getExpectedSubstring());
+ }
- /** {@inheritDoc} */
@Override
- public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
- val actualFileContent = toString(actualFileInputStream);
- if (!actualFileContent.contains(expectedSubstring)) {
- return EnforcerResult.failed(String.format(MESSAGE_TEMPLATE, expectedSubstring));
- }
- return EnforcerResult.passed();
+ protected String getMessageTemplate() {
+ return MESSAGE_TEMPLATE;
}
-
}
\ No newline at end of file
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentEquals.java
index 472108f..1a18a89 100644
--- a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentEquals.java
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentEquals.java
@@ -3,18 +3,10 @@
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.optum.sourcehawk.enforcer.EnforcerResult;
import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.NonNull;
-import lombok.val;
+import lombok.*;
-import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
import java.net.URL;
/**
@@ -25,7 +17,8 @@
@Builder(builderClassName = "Builder")
@JsonDeserialize(builder = ContentEquals.Builder.class)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
-public class ContentEquals extends AbstractFileEnforcer {
+@Getter
+public class ContentEquals extends AbstractContent {
private static final String DEFAULT_MESSAGE = "File contents do not equal that of the expected file contents";
@@ -60,51 +53,8 @@ public static ContentEquals url(final URL expectedUrl) {
return new ContentEquals(null, expectedUrl);
}
- /** {@inheritDoc} */
@Override
- public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
- try (val expectedFileContentsReader = new BufferedReader(resolveReader());
- val actualFileContentsReader = new BufferedReader(new InputStreamReader(actualFileInputStream))) {
- if (equals(expectedFileContentsReader, actualFileContentsReader)) {
- return EnforcerResult.passed();
- }
- }
- return EnforcerResult.failed(DEFAULT_MESSAGE);
+ protected String getDefaultMessage() {
+ return DEFAULT_MESSAGE;
}
-
- /**
- * Resolve the appropriate reader to be used
- *
- * @return the reader of the expected file contents
- * @throws IOException if any error occurs opening file contents from URL
- */
- private Reader resolveReader() throws IOException {
- if (expectedUrl != null) {
- return new InputStreamReader(expectedUrl.openStream());
- } else {
- return new StringReader(expectedFileContents);
- }
- }
-
- /**
- * Determine if the two buffered readers have identical contents
- *
- * @param expectedReader the expected buffered reader
- * @param actualReader the actual buffered reader
- * @return true if content is identical, false otherwise
- * @throws IOException if any error occurs reading files
- */
- private static boolean equals(final BufferedReader expectedReader, final BufferedReader actualReader) throws IOException {
- if (expectedReader == actualReader) {
- return true;
- }
- String line1 = expectedReader.readLine();
- String line2 = actualReader.readLine();
- while (line1 != null && line1.equals(line2)) {
- line1 = expectedReader.readLine();
- line2 = actualReader.readLine();
- }
- return line1 == null && line2 == null;
- }
-
}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentNotEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentNotEquals.java
new file mode 100644
index 0000000..2852e26
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/ContentNotEquals.java
@@ -0,0 +1,75 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * An enforcer which is responsible for enforcing that file contents match exactly
+ *
+ * @author Brian Wyka
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = ContentNotEquals.Builder.class)
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
+@Getter
+public class ContentNotEquals extends AbstractContent {
+
+ private static final String DEFAULT_MESSAGE = "File contents do equal that of the expected file contents";
+
+ /**
+ * The expected file contents
+ */
+ private final String expectedFileContents;
+
+ /**
+ * The URL to use for comparison
+ */
+ private final URL expectedUrl;
+
+ /**
+ * Creates an instance of this enforcer to compare contents the provided contents
+ *
+ * @param expectedFileContents the expected file contents
+ * @return the instance of this enforcer
+ */
+ @SuppressWarnings("squid:S1201")
+ public static ContentNotEquals string(final String expectedFileContents) {
+ return new ContentNotEquals(expectedFileContents, null);
+ }
+
+ /**
+ * Creates an instance of this enforcer to compare contents with URL contents
+ *
+ * @param expectedUrl the URL in which to read expected content
+ * @return the instance of this enforcer
+ */
+ public static ContentNotEquals url(final URL expectedUrl) {
+ return new ContentNotEquals(null, expectedUrl);
+ }
+
+ @Override
+ protected boolean equals(final BufferedReader expectedReader, final BufferedReader actualReader) throws IOException {
+ if (expectedReader == actualReader) {
+ return false;
+ }
+ String line1 = expectedReader.readLine();
+ String line2 = actualReader.readLine();
+ while (line1 != null && !line1.equals(line2)) {
+ line1 = expectedReader.readLine();
+ line2 = actualReader.readLine();
+ }
+ return line1 == null && line2 == null;
+ }
+
+ @Override
+ protected String getDefaultMessage() {
+ return DEFAULT_MESSAGE;
+ }
+}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContains.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContains.java
new file mode 100644
index 0000000..15b53f9
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContains.java
@@ -0,0 +1,34 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import lombok.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An enforcer which is responsible for enforcing that file contains a string
+ *
+ * @author Christian Oestreich
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = NotContains.Builder.class)
+@AllArgsConstructor(staticName = "substring")
+@Getter
+public class NotContains extends AbstractContains {
+
+ private static final String MESSAGE_TEMPLATE = "File does contain the sub string [%s]";
+
+ protected final String expectedSubstring;
+
+ protected boolean passes(String actualFileContent) {
+ return actualFileContent.contains(expectedSubstring);
+ }
+
+ @Override
+ protected String getMessageTemplate() {
+ return MESSAGE_TEMPLATE;
+ }
+}
\ No newline at end of file
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContainsLine.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContainsLine.java
new file mode 100644
index 0000000..152d923
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/NotContainsLine.java
@@ -0,0 +1,50 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.optum.sourcehawk.core.utils.StringUtils;
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * An enforcer which is responsible for enforcing that file contains an entire line
+ *
+ * @author Brian Wyka
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = NotContainsLine.Builder.class)
+@AllArgsConstructor(staticName = "contains")
+public class NotContainsLine extends AbstractFileEnforcer {
+
+ private static final String MESSAGE_TEMPLATE = "File does contain the line [%s]";
+
+ /**
+ * The line that is expected to be found in the file
+ */
+ protected final String expectedLine;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
+ try (val bufferedFileReader = new BufferedReader(new InputStreamReader((actualFileInputStream)))) {
+ String line;
+ while ((line = bufferedFileReader.readLine()) != null) {
+ if (StringUtils.equals(StringUtils.removeNewLines(expectedLine), line)) {
+ return EnforcerResult.failed(String.format(MESSAGE_TEMPLATE, expectedLine));
+ }
+ }
+ }
+ return EnforcerResult.passed();
+ }
+
+}
\ No newline at end of file
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEquals.java
new file mode 100644
index 0000000..cebf12a
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEquals.java
@@ -0,0 +1,65 @@
+package com.optum.sourcehawk.enforcer.file.common;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * An enforcer which is responsible for enforcing that SHA-256 checksum of a file's contents match
+ *
+ * @author Brian Wyka
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = Sha256ChecksumNotEquals.Builder.class)
+@AllArgsConstructor(staticName = "equals")
+public class Sha256ChecksumNotEquals extends AbstractFileEnforcer {
+
+ private static final String ALGORITHM = "SHA-256";
+ private static final String DEFAULT_MESSAGE = "The SHA-256 checksum of the file does match";
+
+ /**
+ * The expected checksum
+ */
+ private final String expectedChecksum;
+
+ /** {@inheritDoc} */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
+ val actualChecksum = checksum(actualFileInputStream);
+ if (!expectedChecksum.equals(actualChecksum)) {
+ return EnforcerResult.passed();
+ }
+ return EnforcerResult.failed(DEFAULT_MESSAGE);
+ }
+
+ private static String checksum(final InputStream inputStream) throws IOException {
+ final MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance(ALGORITHM);
+ } catch (final NoSuchAlgorithmException e) {
+ throw new IOException(e);
+ }
+ val fileContents = toString(inputStream);
+ val encodedHashBytes = digest.digest(fileContents.getBytes(StandardCharsets.UTF_8));
+ val hexStringBuilder = new StringBuilder();
+ for (val encodedHashByte : encodedHashBytes) {
+ val hex = Integer.toHexString(0xff & encodedHashByte);
+ if (hex.length() == 1) {
+ hexStringBuilder.append('0');
+ }
+ hexStringBuilder.append(hex);
+ }
+ return hexStringBuilder.toString();
+ }
+
+}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/AbstractJsonValue.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/AbstractJsonValue.java
new file mode 100644
index 0000000..f925e06
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/AbstractJsonValue.java
@@ -0,0 +1,240 @@
+package com.optum.sourcehawk.enforcer.file.json;
+
+import com.fasterxml.jackson.core.JsonPointer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.optum.sourcehawk.core.utils.StringUtils;
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.ResolverResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import com.optum.sourcehawk.enforcer.file.FileResolver;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * An enforcer implementation which enforces that the result of a JsonPath query equals a specific value
+ *
+ * @author Brian Wyka
+ */
+public abstract class AbstractJsonValue extends AbstractFileEnforcer implements FileResolver {
+
+ protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+ protected static final String READ_ERROR_TEMPLATE = "Reading or parsing file resulted in error [%s]";
+ protected static final String QUERY_ERROR_TEMPLATE = "Execution of pointer expression [%s] yielded error [%s]";
+ protected static final String MISSING_MESSAGE_TEMPLATE = "Execution of pointer expression [%s] yielded no result";
+ protected static final String UPDATE_MESSAGE_TEMPLATE = "Pointer expression [%s] has been updated with value [%s]";
+ protected static final String UPDATE_MISSING_MESSAGE_TEMPLATE = "Pointer expression [%s] which was missing, has been set with value [%s]";
+
+ /**
+ * Update the actual node with the expected value
+ *
+ * @param parentObjectNode the parent object node
+ * @param childNodeName the child node name
+ * @param expectedValue the expected value
+ */
+ private static void updateObjectNodeValue(final ObjectNode parentObjectNode, final String childNodeName, final Object expectedValue) {
+ if (expectedValue instanceof Boolean) {
+ parentObjectNode.put(childNodeName, (boolean) expectedValue);
+ } else if (expectedValue instanceof Integer) {
+ parentObjectNode.put(childNodeName, (int) expectedValue);
+ } else if (expectedValue instanceof Long) {
+ parentObjectNode.put(childNodeName, (long) expectedValue);
+ } else if (expectedValue instanceof Short) {
+ parentObjectNode.put(childNodeName, (short) expectedValue);
+ } else if (expectedValue instanceof BigDecimal) {
+ parentObjectNode.put(childNodeName, (BigDecimal) expectedValue);
+ } else if (expectedValue instanceof BigInteger) {
+ parentObjectNode.put(childNodeName, (BigInteger) expectedValue);
+ } else {
+ parentObjectNode.put(childNodeName, expectedValue.toString());
+ }
+ }
+
+ /**
+ * Update the actual node with the expected value
+ *
+ * @param parentArrayNode the parent object node
+ * @param actualNodeIndex the actual node index in the array
+ * @param expectedValue the expected value
+ * @param missing true if node does not currently exist, false otherwise
+ */
+ @SuppressWarnings("squid:S3776")
+ private static void updateArrayNodeValue(final ArrayNode parentArrayNode, final int actualNodeIndex, final Object expectedValue, final boolean missing) {
+ if (expectedValue instanceof Boolean) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (boolean) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.booleanNode((boolean) expectedValue));
+ }
+ } else if (expectedValue instanceof Integer) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (int) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((int) expectedValue));
+ }
+ } else if (expectedValue instanceof Long) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (long) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((long) expectedValue));
+ }
+ } else if (expectedValue instanceof Short) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (short) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((short) expectedValue));
+ }
+ } else if (expectedValue instanceof BigDecimal) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (BigDecimal) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((BigDecimal) expectedValue));
+ }
+ } else if (expectedValue instanceof BigInteger) {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, (BigInteger) expectedValue);
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((BigInteger) expectedValue));
+ }
+ } else {
+ if (missing) {
+ parentArrayNode.insert(actualNodeIndex, expectedValue.toString());
+ } else {
+ parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.textNode(expectedValue.toString()));
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) {
+ final JsonNode jsonNode;
+ try {
+ jsonNode = OBJECT_MAPPER.readTree(actualFileInputStream);
+ } catch (final IOException e) {
+ return EnforcerResult.failed(String.format(READ_ERROR_TEMPLATE, e.getMessage()));
+ }
+ val messages = getExpectations().entrySet()
+ .stream()
+ .map(entry -> enforce(jsonNode, entry.getKey(), entry.getValue()))
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.toSet());
+ return EnforcerResult.create(messages);
+ }
+
+ /**
+ * Enforce individual json path queries with expected value
+ *
+ * @param jsonNode the JSON node
+ * @param jsonPointerExpression the JSON pointer expression
+ * @param expectedValue the expected value
+ * @return The message to be added, otherwise {@link Optional#empty()}
+ */
+ private Optional enforce(final JsonNode jsonNode, final String jsonPointerExpression, final Object expectedValue) {
+ try {
+ val actualJsonNode = jsonNode.at(JsonPointer.compile(jsonPointerExpression));
+ if (actualJsonNode == null || actualJsonNode.isMissingNode()) {
+ return Optional.of(String.format(MISSING_MESSAGE_TEMPLATE, jsonPointerExpression));
+ }
+ if (jsonNodeValueEquals(actualJsonNode, expectedValue)) {
+ return Optional.empty();
+ }
+ return Optional.of(String.format(getMessageTemplate(), jsonPointerExpression, actualJsonNode.asText(), expectedValue));
+ } catch (final Exception e) {
+ return Optional.of(String.format(QUERY_ERROR_TEMPLATE, jsonPointerExpression, e.getMessage()));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ResolverResult resolve(final @NonNull InputStream actualFileInputStream, final @NonNull Writer outputFileWriter) throws IOException {
+ final JsonNode rootJsonNode;
+ try {
+ rootJsonNode = OBJECT_MAPPER.readTree(actualFileInputStream);
+ } catch (final IOException e) {
+ return ResolverResult.error(String.format(READ_ERROR_TEMPLATE, e.getMessage()));
+ }
+ val resolverResult = getExpectations().entrySet().stream()
+ .map(entry -> resolve(rootJsonNode, entry.getKey(), entry.getValue()))
+ .reduce(ResolverResult.builder().error(true).build(), ResolverResult::reduce);
+ if (resolverResult.isUpdatesApplied()) {
+ outputFileWriter.write(rootJsonNode.toPrettyString());
+ }
+ return resolverResult;
+ }
+
+ /**
+ * Resolve an individual json path query with the expected value
+ *
+ * @param rootJsonNode the root JSON node
+ * @param jsonPointerExpression the JSON pointer expression
+ * @param expectedValue the expected value
+ * @return the resolver result
+ */
+ private ResolverResult resolve(final JsonNode rootJsonNode, final String jsonPointerExpression, final Object expectedValue) {
+ try {
+ val jsonPointer = JsonPointer.compile(jsonPointerExpression);
+ val actualJsonNode = rootJsonNode.at(jsonPointer);
+ final String resolverResultMessage;
+ if (actualJsonNode.isMissingNode()) {
+ resolverResultMessage = String.format(UPDATE_MISSING_MESSAGE_TEMPLATE, jsonPointerExpression, expectedValue);
+ } else {
+ resolverResultMessage = String.format(UPDATE_MESSAGE_TEMPLATE, jsonPointerExpression, expectedValue);
+ }
+ if (jsonNodeValueEquals(actualJsonNode, expectedValue) && !actualJsonNode.isMissingNode()) {
+ return ResolverResult.NO_UPDATES;
+ }
+ val parentNode = rootJsonNode.at(jsonPointer.head());
+ if (parentNode instanceof ObjectNode) {
+ updateObjectNodeValue((ObjectNode) parentNode, jsonPointer.last().toString().substring(1), expectedValue);
+ } else if (parentNode instanceof ArrayNode) {
+ updateArrayNodeValue((ArrayNode) parentNode, Integer.parseInt(jsonPointer.last().toString().substring(1)), expectedValue, actualJsonNode.isMissingNode());
+ } else {
+ return ResolverResult.error("Update not supported for given pointer expression");
+ }
+ return ResolverResult.updatesApplied(resolverResultMessage);
+ } catch (final Exception e) {
+ return ResolverResult.error(String.format(QUERY_ERROR_TEMPLATE, jsonPointerExpression, e.getMessage()));
+ }
+ }
+
+ /**
+ * Determine if the {@code jsonNode} value equals that of the {@code expectedValue}
+ *
+ * @param jsonNode the JSON node to retrieve the value from
+ * @param expectedValue the expected value
+ * @return true if they are equal, false otherwise
+ */
+ protected boolean jsonNodeValueEquals(final JsonNode jsonNode, final Object expectedValue) {
+ return (expectedValue instanceof CharSequence && StringUtils.equals((CharSequence) expectedValue, jsonNode.textValue()))
+ || (expectedValue instanceof Number && expectedValue == jsonNode.numberValue())
+ || (expectedValue instanceof Boolean && (boolean) expectedValue == jsonNode.booleanValue())
+ || Objects.equals(expectedValue.toString(), jsonNode.asText());
+ }
+
+ protected abstract Map getExpectations();
+
+ protected abstract String getMessageTemplate();
+
+ protected boolean skipMissingNode() {
+ return false;
+ }
+}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueEquals.java
index 082d6b7..939aad3 100644
--- a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueEquals.java
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueEquals.java
@@ -1,54 +1,30 @@
package com.optum.sourcehawk.enforcer.file.json;
-import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import com.optum.sourcehawk.core.utils.StringUtils;
-import com.optum.sourcehawk.enforcer.EnforcerResult;
-import com.optum.sourcehawk.enforcer.ResolverResult;
-import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
import com.optum.sourcehawk.enforcer.file.FileResolver;
import lombok.AllArgsConstructor;
import lombok.Builder;
-import lombok.NonNull;
-import lombok.val;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.math.BigDecimal;
-import java.math.BigInteger;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
-import java.util.stream.Collectors;
/**
* An enforcer implementation which enforces that the result of a JsonPath query equals a specific value
*
* @author Brian Wyka
+ * @author Christian Oestreich
*/
@Builder(builderClassName = "Builder")
@JsonDeserialize(builder = JsonValueEquals.Builder.class)
@AllArgsConstructor(staticName = "equals")
-public class JsonValueEquals extends AbstractFileEnforcer implements FileResolver {
-
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
- private static final String READ_ERROR_TEMPLATE = "Reading or parsing file resulted in error [%s]";
- private static final String QUERY_ERROR_TEMPLATE = "Execution of pointer expression [%s] yielded error [%s]";
- private static final String MISSING_MESSAGE_TEMPLATE = "Execution of pointer expression [%s] yielded no result";
- private static final String NOT_EQUAL_MESSAGE_TEMPLATE = "Execution of pointer expression [%s] yielded result [%s] which is not equal to [%s]";
- private static final String UPDATE_MESSAGE_TEMPLATE = "Pointer expression [%s] has been updated with value [%s]";
- private static final String UPDATE_MISSING_MESSAGE_TEMPLATE = "Pointer expression [%s] which was missing, has been set with value [%s]";
+public class JsonValueEquals extends AbstractJsonValue implements FileResolver {
/**
* Key: The JsonPointer expression to retrieve the value
- *
+ *
* Value: The expected value which the query should evaluate to
*/
private final Map expectations;
@@ -57,199 +33,19 @@ public class JsonValueEquals extends AbstractFileEnforcer implements FileResolve
* Create with a single path query and expected value
*
* @param jsonPointerExpression the JSON pointer expression
- * @param expectedValue the expected value
+ * @param expectedValue the expected value
* @return the enforcer
*/
public static JsonValueEquals equals(final String jsonPointerExpression, final Object expectedValue) {
return JsonValueEquals.equals(Collections.singletonMap(jsonPointerExpression, expectedValue));
}
- /** {@inheritDoc} */
@Override
- public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) {
- final JsonNode jsonNode;
- try {
- jsonNode = OBJECT_MAPPER.readTree(actualFileInputStream);
- } catch (final IOException e) {
- return EnforcerResult.failed(String.format(READ_ERROR_TEMPLATE, e.getMessage()));
- }
- val messages = expectations.entrySet()
- .stream()
- .map(entry -> enforce(jsonNode, entry.getKey(), entry.getValue()))
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(Collectors.toSet());
- return EnforcerResult.create(messages);
- }
-
- /**
- * Enforce individual json path queries with expected value
- *
- * @param jsonNode the JSON node
- * @param jsonPointerExpression the JSON pointer expression
- * @param expectedValue the expected value
- * @return The message to be added, otherwise {@link Optional#empty()}
- */
- private static Optional enforce(final JsonNode jsonNode, final String jsonPointerExpression, final Object expectedValue) {
- try {
- val actualJsonNode = jsonNode.at(JsonPointer.compile(jsonPointerExpression));
- if (actualJsonNode == null || actualJsonNode.isMissingNode()) {
- return Optional.of(String.format(MISSING_MESSAGE_TEMPLATE, jsonPointerExpression));
- }
- if (jsonNodeValueEquals(actualJsonNode, expectedValue)) {
- return Optional.empty();
- }
- return Optional.of(String.format(NOT_EQUAL_MESSAGE_TEMPLATE, jsonPointerExpression, actualJsonNode.asText(), expectedValue));
- } catch (final Exception e) {
- return Optional.of(String.format(QUERY_ERROR_TEMPLATE, jsonPointerExpression, e.getMessage()));
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public ResolverResult resolve(final @NonNull InputStream actualFileInputStream, final @NonNull Writer outputFileWriter) throws IOException {
- final JsonNode rootJsonNode;
- try {
- rootJsonNode = OBJECT_MAPPER.readTree(actualFileInputStream);
- } catch (final IOException e) {
- return ResolverResult.error(String.format(READ_ERROR_TEMPLATE, e.getMessage()));
- }
- val resolverResult = expectations.entrySet().stream()
- .map(entry -> resolve(rootJsonNode, entry.getKey(), entry.getValue()))
- .reduce(ResolverResult.builder().error(true).build(), ResolverResult::reduce);
- if (resolverResult.isUpdatesApplied()) {
- outputFileWriter.write(rootJsonNode.toPrettyString());
- }
- return resolverResult;
- }
-
- /**
- * Resolve an individual json path query with the expected value
- *
- * @param rootJsonNode the root JSON node
- * @param jsonPointerExpression the JSON pointer expression
- * @param expectedValue the expected value
- * @return the resolver result
- */
- private static ResolverResult resolve(final JsonNode rootJsonNode, final String jsonPointerExpression, final Object expectedValue) {
- try {
- val jsonPointer = JsonPointer.compile(jsonPointerExpression);
- val actualJsonNode = rootJsonNode.at(jsonPointer);
- final String resolverResultMessage;
- if (actualJsonNode.isMissingNode()) {
- resolverResultMessage = String.format(UPDATE_MISSING_MESSAGE_TEMPLATE, jsonPointerExpression, expectedValue);
- } else {
- resolverResultMessage = String.format(UPDATE_MESSAGE_TEMPLATE, jsonPointerExpression, expectedValue);
- }
- if (jsonNodeValueEquals(actualJsonNode, expectedValue)) {
- return ResolverResult.NO_UPDATES;
- }
- val parentNode = rootJsonNode.at(jsonPointer.head());
- if (parentNode instanceof ObjectNode) {
- updateObjectNodeValue((ObjectNode) parentNode, jsonPointer.last().toString().substring(1), expectedValue);
- } else if (parentNode instanceof ArrayNode) {
- updateArrayNodeValue((ArrayNode) parentNode, Integer.parseInt(jsonPointer.last().toString().substring(1)), expectedValue, actualJsonNode.isMissingNode());
- } else {
- return ResolverResult.error("Update not supported for given pointer expression");
- }
- return ResolverResult.updatesApplied(resolverResultMessage);
- } catch (final Exception e) {
- return ResolverResult.error(String.format(QUERY_ERROR_TEMPLATE, jsonPointerExpression, e.getMessage()));
- }
+ protected Map getExpectations() {
+ return this.expectations;
}
- /**
- * Update the actual node with the expected value
- *
- * @param parentObjectNode the parent object node
- * @param childNodeName the child node name
- * @param expectedValue the expected value
- */
- private static void updateObjectNodeValue(final ObjectNode parentObjectNode, final String childNodeName, final Object expectedValue) {
- if (expectedValue instanceof Boolean) {
- parentObjectNode.put(childNodeName, (boolean) expectedValue);
- } else if (expectedValue instanceof Integer) {
- parentObjectNode.put(childNodeName, (int) expectedValue);
- } else if (expectedValue instanceof Long) {
- parentObjectNode.put(childNodeName, (long) expectedValue);
- } else if (expectedValue instanceof Short) {
- parentObjectNode.put(childNodeName, (short) expectedValue);
- } else if (expectedValue instanceof BigDecimal) {
- parentObjectNode.put(childNodeName, (BigDecimal) expectedValue);
- } else if (expectedValue instanceof BigInteger) {
- parentObjectNode.put(childNodeName, (BigInteger) expectedValue);
- } else {
- parentObjectNode.put(childNodeName, expectedValue.toString());
- }
+ protected String getMessageTemplate(){
+ return "Execution of pointer expression [%s] yielded result [%s] which is not equal to [%s]";
}
-
- /**
- * Update the actual node with the expected value
- *
- * @param parentArrayNode the parent object node
- * @param actualNodeIndex the actual node index in the array
- * @param expectedValue the expected value
- * @param missing true if node does not currently exist, false otherwise
- */
- @SuppressWarnings("squid:S3776")
- private static void updateArrayNodeValue(final ArrayNode parentArrayNode, final int actualNodeIndex, final Object expectedValue, final boolean missing) {
- if (expectedValue instanceof Boolean) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (boolean) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.booleanNode((boolean) expectedValue));
- }
- } else if (expectedValue instanceof Integer) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (int) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((int) expectedValue));
- }
- } else if (expectedValue instanceof Long) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (long) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((long) expectedValue));
- }
- } else if (expectedValue instanceof Short) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (short) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((short) expectedValue));
- }
- } else if (expectedValue instanceof BigDecimal) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (BigDecimal) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((BigDecimal) expectedValue));
- }
- } else if (expectedValue instanceof BigInteger) {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, (BigInteger) expectedValue);
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.numberNode((BigInteger) expectedValue));
- }
- } else {
- if (missing) {
- parentArrayNode.insert(actualNodeIndex, expectedValue.toString());
- } else {
- parentArrayNode.set(actualNodeIndex, JsonNodeFactory.instance.textNode(expectedValue.toString()));
- }
- }
- }
-
- /**
- * Determine if the {@code jsonNode} value equals that of the {@code expectedValue}
- *
- * @param jsonNode the JSON node to retrieve the value from
- * @param expectedValue the expected value
- * @return true if they are equal, false otherwise
- */
- private static boolean jsonNodeValueEquals(final JsonNode jsonNode, final Object expectedValue) {
- return (expectedValue instanceof CharSequence && StringUtils.equals((CharSequence) expectedValue, jsonNode.textValue()))
- || (expectedValue instanceof Number && expectedValue == jsonNode.numberValue())
- || (expectedValue instanceof Boolean && (boolean) expectedValue == jsonNode.booleanValue())
- || Objects.equals(expectedValue.toString(), jsonNode.asText());
- }
-
}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEquals.java
new file mode 100644
index 0000000..b0982cb
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEquals.java
@@ -0,0 +1,76 @@
+package com.optum.sourcehawk.enforcer.file.json;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.optum.sourcehawk.core.utils.StringUtils;
+import com.optum.sourcehawk.enforcer.file.FileResolver;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * An enforcer implementation which enforces that the result of a JsonPath query does not equal a specific value
+ *
+ * @author Brian Wyka
+ * @author Christian Oestreich
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = JsonValueNotEquals.Builder.class)
+@AllArgsConstructor(staticName = "equals")
+public class JsonValueNotEquals extends AbstractJsonValue implements FileResolver {
+
+ /**
+ * Key: The JsonPointer expression to retrieve the value
+ *
+ * Value: The expected value which the query should evaluate to
+ */
+ private final Map expectations;
+
+ /**
+ * Create with a single path query and expected value
+ *
+ * @param jsonPointerExpression the JSON pointer expression
+ * @param expectedValue the expected value
+ * @return the enforcer
+ */
+ public static JsonValueNotEquals equals(final String jsonPointerExpression, final Object expectedValue) {
+ return JsonValueNotEquals.equals(Collections.singletonMap(jsonPointerExpression, expectedValue));
+ }
+
+ /**
+ * Determine if the {@code jsonNode} value equals that of the {@code expectedValue}
+ *
+ * @param jsonNode the JSON node to retrieve the value from
+ * @param expectedValue the expected value
+ * @return true if they are equal, false otherwise
+ */
+ protected boolean jsonNodeValueEquals(final JsonNode jsonNode, final Object expectedValue) {
+ if (expectedValue instanceof CharSequence) {
+ return !StringUtils.equals((CharSequence) expectedValue, jsonNode.textValue());
+ }
+ if (expectedValue instanceof Number) {
+ return expectedValue != jsonNode.numberValue();
+ }
+ if (expectedValue instanceof Boolean) {
+ return (boolean) expectedValue != jsonNode.booleanValue();
+ }
+ return !Objects.equals(expectedValue.toString(), jsonNode.asText());
+ }
+
+ @Override
+ protected Map getExpectations() {
+ return this.expectations;
+ }
+
+ @Override
+ protected String getMessageTemplate() {
+ return "Execution of pointer expression [%s] yielded result [%s] which does equal [%s]";
+ }
+
+ protected boolean skipMissingNode(){
+ return true;
+ }
+}
diff --git a/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEquals.java b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEquals.java
new file mode 100644
index 0000000..069c0c4
--- /dev/null
+++ b/enforcer/file/common/src/main/java/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEquals.java
@@ -0,0 +1,69 @@
+package com.optum.sourcehawk.enforcer.file.yaml;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+import com.optum.sourcehawk.enforcer.EnforcerResult;
+import com.optum.sourcehawk.enforcer.file.AbstractFileEnforcer;
+import com.optum.sourcehawk.enforcer.file.json.JsonValueEquals;
+import com.optum.sourcehawk.enforcer.file.json.JsonValueNotEquals;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.NonNull;
+import lombok.val;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * An enforcer which is responsible for enforcing that a yaml file has a specific property with an expected value. Under
+ * the hood, this is delegating to {@link JsonValueEquals} after converting the yaml to json
+ *
+ * @author Christian Oestreich
+ * @see JsonValueNotEquals
+ */
+@Builder(builderClassName = "Builder")
+@JsonDeserialize(builder = YamlValueNotEquals.Builder.class)
+@AllArgsConstructor(staticName = "equals")
+public class YamlValueNotEquals extends AbstractFileEnforcer {
+
+ private static final ObjectMapper YAML_MAPPER = new YAMLMapper();
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ /**
+ * Key: The Yaml Pointer expression to retrieve the value
+ *
+ * Value: The expected value which the query should evaluate to
+ */
+ private final Map expectations;
+
+ /**
+ * Create with a single path query and expected value
+ *
+ * @param yamlPathQuery the yaml path query
+ * @param expectedValue the expected value
+ * @return the enforcer
+ */
+ public static YamlValueNotEquals equals(final String yamlPathQuery, final Object expectedValue) {
+ return YamlValueNotEquals.equals(Collections.singletonMap(yamlPathQuery, expectedValue));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EnforcerResult enforceInternal(@NonNull final InputStream actualFileInputStream) throws IOException {
+ val yamlMap = YAML_MAPPER.readValue(actualFileInputStream, new TypeReference>() {
+ });
+ val json = OBJECT_MAPPER.writeValueAsString(yamlMap);
+ try (val jsonInputStream = new ByteArrayInputStream(json.getBytes(Charset.defaultCharset()))) {
+ return JsonValueNotEquals.equals(expectations).enforce(jsonInputStream);
+ }
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/ContentNotEqualsSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/ContentNotEqualsSpec.groovy
new file mode 100644
index 0000000..669c46c
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/ContentNotEqualsSpec.groovy
@@ -0,0 +1,80 @@
+package com.optum.sourcehawk.enforcer.file.common
+
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+
+class ContentNotEqualsSpec extends Specification {
+
+ def "string"() {
+ expect:
+ ContentNotEquals.string('file')
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ ContentNotEquals.string("abc").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ def "enforce (passed)"() {
+ given:
+ ContentNotEquals contentNotEquals = ContentNotEquals.string(IoUtil.getResourceAsStream('/file.txt').text)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/file.txt')
+
+ when:
+ EnforcerResult result = contentNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "File contents do equal that of the expected file contents"
+ }
+
+ def "enforce (failed)"() {
+ given:
+ ContentNotEquals contentNotEquals = ContentNotEquals.string(IoUtil.getResourceAsStream('/file.txt').text)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/checksum.txt')
+
+ when:
+ EnforcerResult result = contentNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+ }
+
+ def "enforce - URL (passed)"() {
+ given:
+ ContentNotEquals notEquals = ContentNotEquals.url(new URL('https://raw.githubusercontent.com/optum/sourcehawk/main/README.md'))
+ InputStream fileInputStream = new URL('https://raw.githubusercontent.com/optum/sourcehawk/main/README.md').openStream()
+
+ when:
+ EnforcerResult result = notEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "File contents do equal that of the expected file contents"
+ }
+
+ def "enforce - URL (failed)"() {
+ given:
+ ContentNotEquals contentNotEquals = ContentNotEquals.url(new URL('https://raw.githubusercontent.com/optum/sourcehawk/main/README.md'))
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/checksum.txt')
+
+ when:
+ EnforcerResult result = contentNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsLineSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsLineSpec.groovy
new file mode 100644
index 0000000..4c3a555
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsLineSpec.groovy
@@ -0,0 +1,66 @@
+package com.optum.sourcehawk.enforcer.file.common
+
+
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class NotContainsLineSpec extends Specification {
+
+ def "equals"() {
+ expect:
+ NotContainsLine.contains('I am a line')
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ NotContainsLine.contains("line").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ @Unroll
+ def "enforce - #expectedLine (passed)"() {
+ given:
+ NotContainsLine notContainsLine = NotContainsLine.contains(expectedLine)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/file.txt')
+
+ when:
+ EnforcerResult result = notContainsLine.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages[0] == "File does contain the line [$expectedLine]"
+
+ where:
+ expectedLine << [
+ '^ Here is a special character: $',
+ 'Perhaps I should include a double " and a single \' as well...'
+ ]
+ }
+
+ @Unroll
+ def "enforce - #expectedLine (failed)"() {
+ given:
+ NotContainsLine notContainsLine = NotContainsLine.contains(expectedLine)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/file.txt')
+
+ when:
+ EnforcerResult result = notContainsLine.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+
+ where:
+ expectedLine << [
+ 'Here is a special character: $',
+ 'Perhaps I should include a double " and a single \' as well'
+ ]
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsSpec.groovy
new file mode 100644
index 0000000..46e3d77
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/NotContainsSpec.groovy
@@ -0,0 +1,67 @@
+package com.optum.sourcehawk.enforcer.file.common
+
+
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class NotContainsSpec extends Specification {
+
+ def "equals"() {
+ expect:
+ NotContains.substring('Hello')
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ NotContains.substring("abc").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ @Unroll
+ def "enforce - #expectedSubstring (passed)"() {
+ given:
+ NotContains notContains = NotContains.substring(expectedSubstring)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/file.txt')
+
+ when:
+ EnforcerResult result = notContains.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+
+ where:
+ expectedSubstring << [
+ 'imaginary',
+ 'I should not include'
+ ]
+ }
+
+ @Unroll
+ def "enforce - #expectedSubstring (failed)"() {
+ given:
+ NotContains notContains = NotContains.substring(expectedSubstring)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/file.txt')
+
+ when:
+ EnforcerResult result = notContains.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "File does contain the sub string [$expectedSubstring]"
+
+ where:
+ expectedSubstring << [
+ 'special',
+ 'Perhaps I should include'
+ ]
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEqualsSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEqualsSpec.groovy
new file mode 100644
index 0000000..862f59e
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/common/Sha256ChecksumNotEqualsSpec.groovy
@@ -0,0 +1,54 @@
+package com.optum.sourcehawk.enforcer.file.common
+
+
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+
+class Sha256ChecksumNotEqualsSpec extends Specification {
+
+ def "equals"() {
+ expect:
+ Sha256ChecksumNotEquals.equals("checksum")
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ Sha256ChecksumNotEquals.equals("abc").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ def "enforce (passed))"() {
+ given:
+ String expectedChecksum = "a6179a1feff6949517fab1d18804a35d25d807c597fcba21a6b4c3e919af6e6f"
+ Sha256ChecksumNotEquals sha256ChecksumNotEquals = Sha256ChecksumNotEquals.equals(expectedChecksum)
+ InputStream fileInputStream = IoUtil.getResourceAsStream("/checksum.txt")
+
+ when:
+ EnforcerResult enforcerResult = sha256ChecksumNotEquals.enforce(fileInputStream)
+
+ then:
+ enforcerResult
+ !enforcerResult.passed
+ enforcerResult.messages
+ enforcerResult.messages[0] == 'The SHA-256 checksum of the file does match'
+ }
+
+ def "enforce (failed))"() {
+ given:
+ String expectedChecksum = "123"
+ Sha256ChecksumNotEquals sha256ChecksumNotEquals = Sha256ChecksumNotEquals.equals(expectedChecksum)
+ InputStream fileInputStream = IoUtil.getResourceAsStream("/checksum.txt")
+
+ when:
+ EnforcerResult enforcerResult = sha256ChecksumNotEquals.enforce(fileInputStream)
+
+ then:
+ enforcerResult
+ enforcerResult.passed
+ !enforcerResult.messages
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEqualsSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEqualsSpec.groovy
new file mode 100644
index 0000000..12a5208
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/json/JsonValueNotEqualsSpec.groovy
@@ -0,0 +1,401 @@
+package com.optum.sourcehawk.enforcer.file.json
+
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.node.ArrayNode
+import com.fasterxml.jackson.databind.node.JsonNodeFactory
+import com.fasterxml.jackson.databind.node.ObjectNode
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import com.optum.sourcehawk.enforcer.ResolverResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+import spock.lang.Unroll
+
+import java.util.function.Function
+
+class JsonValueNotEqualsSpec extends Specification {
+
+ def "equals"() {
+ expect:
+ JsonValueNotEquals.equals('/key', 'value')
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ JsonValueNotEquals.equals('/foo', "bar").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (passed)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+
+ where:
+ pointerExpression | expectedValue
+ '/make' | 'Trek'
+ '/size/value' | 61
+ '/components/0' | 'shifter'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (passed) - number based keys"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/index-map.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+
+ where:
+ pointerExpression | expectedValue
+ '/index/0' | 'hello1'
+ '/index/1' | 'world1'
+ '/index/2' | 'foo1'
+ '/index/3' | 'bar1'
+ }
+
+ def "enforce - map (passed)"() {
+ given:
+ def map = [
+ '/make' : 'Trek',
+ '/size/value' : 61,
+ '/components/0' : 'shifter'
+ ]
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(map)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - incorrect value)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "Execution of pointer expression [$pointerExpression] yielded result [$actualValue] which does equal [$expectedValue]"
+
+ where:
+ pointerExpression | actualValue | expectedValue
+ '/make' | 'Raleigh' | 'Raleigh'
+ '/size/value' | 60 | 60
+ '/components/0' | 'handlebars' | 'handlebars'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - missing)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "Execution of pointer expression [$pointerExpression] yielded no result"
+
+ where:
+ pointerExpression | expectedValue
+ '/class' | 'road'
+ '/components/8' | 'calipers'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - pointer expression error)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0].startsWith("Execution of pointer expression [$pointerExpression] yielded error")
+
+ where:
+ pointerExpression | expectedValue
+ '*' | 'road'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - null parse)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle-bad.json')
+
+ when:
+ EnforcerResult result = jsonPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0].startsWith("Reading or parsing file resulted in error")
+
+ where:
+ pointerExpression | expectedValue
+ '//' | 'road'
+ }
+
+ @Unroll
+ def "resolve - no updates required"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+ StringWriter stringWriter = new StringWriter()
+
+ when:
+ ResolverResult result = jsonPathNotEquals.resolve(fileInputStream, stringWriter)
+
+ then:
+ result
+ !result.updatesApplied
+ result.fixCount == 0
+ !result.error
+ result.errorCount == 0
+ !result.messages
+
+ and:
+ !stringWriter.toString()
+
+ where:
+ pointerExpression | expectedValue
+ '/make' | 'Trek'
+ '/size/value' | 61
+ '/components/0' | 'brakes'
+ }
+
+ @Unroll
+ def "resolve - updates applied (pointer expression found)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+ StringWriter stringWriter = new StringWriter()
+
+ when:
+ ResolverResult result = jsonPathNotEquals.resolve(fileInputStream, stringWriter)
+
+ then:
+ result
+ result.updatesApplied
+ result.fixCount == 1
+ !result.error
+ result.errorCount == 0
+ result.messages
+ result.messages.size() == 1
+ result.messages[0] == "Pointer expression [$pointerExpression] has been updated with value [$expectedValue]"
+
+ and:
+ stringWriter.toString()
+
+ where:
+ pointerExpression | expectedValue
+ '/make' | 'Raleigh'
+ '/size/value' | 60
+ '/components/0' | 'handlebars'
+ }
+
+ @Unroll
+ def "resolve - updates applied (pointer expression not found)"() {
+ given:
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+ StringWriter stringWriter = new StringWriter()
+
+ when:
+ ResolverResult result = jsonPathNotEquals.resolve(fileInputStream, stringWriter)
+
+ then:
+ result
+ result.updatesApplied
+ result.fixCount == 1
+ !result.error
+ result.errorCount == 0
+ result.messages
+ result.messages.size() == 1
+ result.messages[0] == "Pointer expression [$pointerExpression] which was missing, has been set with value [$expectedValue]"
+
+ when:
+ Map jsonObject = new ObjectMapper().readValue(stringWriter.toString(), Map)
+
+ then:
+ expectedJsonAssertion.apply(jsonObject)
+
+ where:
+ pointerExpression | expectedValue | expectedJsonAssertion
+ '/rating' | 98 | { json -> json.rating == 98 } as Function
+// '/notes/0' | 'Note 1' | { json -> json.notes[0] == "Note 1" } as Function (array addition not yet supported)
+// '/child/notes/0' | 'Child Note' | { json -> json['child.notes'][0] == "Child Note" } as Function (array addition not yet supported)
+ }
+
+ def "resolve - error"() {
+ given:
+ String pointerExpression = '$$'
+ JsonValueNotEquals jsonPathNotEquals = JsonValueNotEquals.equals(pointerExpression, "doesn't matter")
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.json')
+ StringWriter stringWriter = new StringWriter()
+
+ when:
+ ResolverResult result = jsonPathNotEquals.resolve(fileInputStream, stringWriter)
+
+ then:
+ result
+ !result.updatesApplied
+ result.fixCount == 0
+ result.error
+ result.errorCount == 1
+ result.messages
+ result.messages.size() == 1
+ result.messages[0].startsWith("Execution of pointer expression [$pointerExpression] yielded error")
+
+ and:
+ !stringWriter.toString()
+ }
+
+ def "resolve - closed input stream"() {
+ given:
+ InputStream inputStream = IoUtil.getResourceAsStream('/bicycle.json')
+ inputStream.close()
+
+ when:
+ ResolverResult resolverResult = JsonValueNotEquals.equals('/key', "doesn't matter").resolve(inputStream, new StringWriter())
+
+ then:
+ resolverResult
+ !resolverResult.updatesApplied
+ resolverResult.fixCount == 0
+ resolverResult.error
+ resolverResult.errorCount == 1
+ resolverResult.messages
+ resolverResult.messages.size() == 1
+ resolverResult.messages[0].startsWith("Reading or parsing file resulted in error")
+ }
+
+ def "resolve - null input stream or writer"() {
+ when:
+ JsonValueNotEquals.equals('/key', "doesn't matter").resolve(null, new StringWriter())
+
+ then:
+ thrown(NullPointerException)
+
+ when:
+ JsonValueNotEquals.equals('/key', "doesn't matter").resolve( IoUtil.getResourceAsStream('/bicycle.json'), null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ @Unroll
+ def "updateObjectNodeValue - #type"() {
+ given:
+ ObjectNode parentObjectNode = JsonNodeFactory.instance.objectNode()
+ String childNodeName = "child"
+
+ when:
+ JsonValueNotEquals.updateObjectNodeValue(parentObjectNode, childNodeName, expectedValue)
+
+ then:
+ noExceptionThrown()
+
+ where:
+ type | expectedValue
+ String | "hello"
+ Boolean | true
+ Integer | (int) 34
+ Long | (long) 28
+ Double | (double) 20.4
+ Float | (float) 100.7345
+ Short | (short) 1
+ BigInteger | BigInteger.ONE
+ BigDecimal | BigDecimal.ZERO
+ }
+
+ @Unroll
+ def "updateArrayNodeValue - #type (missing = false)"() {
+ given:
+ ArrayNode parentArrayNode = JsonNodeFactory.instance.arrayNode(10)
+ parentArrayNode.add(expectedValue)
+ parentArrayNode.add(expectedValue)
+ parentArrayNode.add(expectedValue)
+ parentArrayNode.add(expectedValue)
+ parentArrayNode.add(expectedValue)
+ parentArrayNode.add(expectedValue)
+ int childNodeIndex = 3
+
+ when:
+ JsonValueNotEquals.updateArrayNodeValue(parentArrayNode, childNodeIndex, expectedValue, false)
+
+ then:
+ noExceptionThrown()
+
+ where:
+ type | expectedValue
+ String | "hello"
+ Boolean | true
+ Integer | (int) 34
+ Long | (long) 28
+ Short | (short) 1
+ BigInteger | BigInteger.ONE
+ BigDecimal | BigDecimal.ZERO
+ }
+
+ @Unroll
+ def "updateArrayNodeValue - #type (missing = true)"() {
+ given:
+ ArrayNode parentArrayNode = JsonNodeFactory.instance.arrayNode(10)
+ int childNodeIndex = 3
+
+ when:
+ JsonValueNotEquals.updateArrayNodeValue(parentArrayNode, childNodeIndex, expectedValue, true)
+
+ then:
+ noExceptionThrown()
+
+ where:
+ type | expectedValue
+ String | "hello"
+ Boolean | true
+ Integer | (int) 34
+ Long | (long) 28
+ Short | (short) 1
+ BigInteger | BigInteger.ONE
+ BigDecimal | BigDecimal.ZERO
+ }
+
+}
diff --git a/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEqualsSpec.groovy b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEqualsSpec.groovy
new file mode 100644
index 0000000..6b75d6b
--- /dev/null
+++ b/enforcer/file/common/src/test/groovy/com/optum/sourcehawk/enforcer/file/yaml/YamlValueNotEqualsSpec.groovy
@@ -0,0 +1,127 @@
+package com.optum.sourcehawk.enforcer.file.yaml
+
+
+import com.optum.sourcehawk.enforcer.EnforcerResult
+import org.spockframework.util.IoUtil
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class YamlValueNotEqualsSpec extends Specification {
+
+ def "equals"() {
+ expect:
+ YamlValueNotEquals.equals('/key', 'value')
+ YamlValueNotEquals.equals(['/key': 'value'])
+ }
+
+ def "enforce - null input stream"() {
+ when:
+ YamlValueNotEquals.equals('/foo', "bar").enforceInternal(null)
+
+ then:
+ thrown(NullPointerException)
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (passed)"() {
+ given:
+ YamlValueNotEquals yamlPathNotEquals = YamlValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.yml')
+
+ when:
+ EnforcerResult result = yamlPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+
+ where:
+ pointerExpression | expectedValue
+ '/make' | 'Trek'
+ '/size/value' | 61
+ '/components/0' | 'brakes'
+ }
+
+ def "enforce - map (passed)"() {
+ given:
+ def map = [
+ '/make' : 'Trek',
+ '/size/value' : 61,
+ '/components/0': 'brakes'
+ ]
+ YamlValueNotEquals yamlPathNotEquals = YamlValueNotEquals.equals(map)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.yml')
+
+ when:
+ EnforcerResult result = yamlPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ result.passed
+ !result.messages
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - incorrect value)"() {
+ given:
+ YamlValueNotEquals yamlPathNotEquals = YamlValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.yml')
+
+ when:
+ EnforcerResult result = yamlPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "Execution of pointer expression [$pointerExpression] yielded result [$actualValue] which does equal [$expectedValue]"
+
+ where:
+ pointerExpression | actualValue | expectedValue
+ '/make' | 'Raleigh' | 'Raleigh'
+ '/size/value' | 60 | 60
+ '/components/0' | 'handlebars' | 'handlebars'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression = #expectedValue (failed - missing)"() {
+ given:
+ YamlValueNotEquals yamlPathNotEquals = YamlValueNotEquals.equals(pointerExpression, expectedValue)
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.yml')
+
+ when:
+ EnforcerResult result = yamlPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0] == "Execution of pointer expression [$pointerExpression] yielded no result"
+
+ where:
+ pointerExpression | expectedValue
+ '/class' | 'road'
+ '/components/8' | 'calipers'
+ }
+
+ @Unroll
+ def "enforce - #pointerExpression (failed - pointer expression error)"() {
+ given:
+ YamlValueNotEquals yamlPathNotEquals = YamlValueNotEquals.equals(pointerExpression, 'road')
+ InputStream fileInputStream = IoUtil.getResourceAsStream('/bicycle.yml')
+
+ when:
+ EnforcerResult result = yamlPathNotEquals.enforce(fileInputStream)
+
+ then:
+ result
+ !result.passed
+ result.messages
+ result.messages[0].startsWith("Execution of pointer expression [$pointerExpression] yielded error")
+
+ where:
+ pointerExpression << ['.', '$']
+ }
+
+}