From d58e8e58143f8ec0b8d669fb289bf23cb5f70b0b Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Mon, 27 Oct 2025 14:25:03 +0100 Subject: [PATCH 1/7] Use Java 17 --- java/pom.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index aeaa6ec8..716f291c 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -6,7 +6,7 @@ io.cucumber cucumber-parent - 4.5.0 + 5.0.0-SNAPSHOT ci-environment @@ -109,10 +109,6 @@ org.apache.maven.plugins maven-compiler-plugin - - - true - generate-ci-environments @@ -127,6 +123,7 @@ + org.codehaus.mojo From ba9c34c00948c9b343c2314cf43921d675cdc95f Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Tue, 4 Nov 2025 12:51:07 +0100 Subject: [PATCH 2/7] Use StringBuilder instead of StringBuffer --- .../main/java/io/cucumber/cienvironment/VariableExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java b/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java index 8ee9385b..d23ffe7e 100644 --- a/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java +++ b/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java @@ -16,7 +16,7 @@ private VariableExpression() { static String evaluate(String expression, Map env) { if (expression == null) return null; Matcher variableMatcher = variablePattern.matcher(expression); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); while (variableMatcher.find()) { String variable = variableMatcher.group(1); String value = getValue(env, variable); From 174e2fd6f9cbc35dcededcdb1f8b8ee950f9cf0e Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Tue, 4 Nov 2025 13:49:06 +0100 Subject: [PATCH 3/7] Use Error Prone and JSpecify --- java/.mvn/jvm.config | 10 +++++ java/pom.xml | 8 +++- .../cucumber/cienvironment}/Generate.java | 2 + .../templates/ci-environments.java.ftl | 0 .../cienvironment/CiEnvironmentImpl.java | 22 ++++++----- .../cienvironment/DetectCiEnvironment.java | 12 +++--- .../cienvironment/GithubEventParser.java | 13 ++++--- .../cienvironment/RemoveUserInfo.java | 2 +- .../cienvironment/VariableExpression.java | 6 ++- .../cucumber/cienvironment/package-info.java | 4 ++ .../DetectCiEnvironmentTest.java | 13 ++++--- .../GitHubPullRequestIntegrationTest.java | 4 +- .../cienvironment/RemoveUserInfoTest.java | 5 --- .../cienvironment/VariableExpressionTest.java | 37 ++++++++----------- 14 files changed, 79 insertions(+), 59 deletions(-) create mode 100644 java/.mvn/jvm.config rename java/src/codegen/java/{ => io/cucumber/cienvironment}/Generate.java (98%) rename java/src/codegen/resources/{ => io/cucumber/cienvironment}/templates/ci-environments.java.ftl (100%) create mode 100644 java/src/main/java/io/cucumber/cienvironment/package-info.java diff --git a/java/.mvn/jvm.config b/java/.mvn/jvm.config new file mode 100644 index 00000000..8488a4fc --- /dev/null +++ b/java/.mvn/jvm.config @@ -0,0 +1,10 @@ +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ No newline at end of file diff --git a/java/pom.xml b/java/pom.xml index 716f291c..36d01552 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -49,6 +49,12 @@ + + org.jspecify + jspecify + 1.0.0 + + org.junit.jupiter junit-jupiter @@ -143,7 +149,7 @@ ${project.build.directory}/codegen-classes - Generate + io.cucumber.cienvironment.Generate ${project.build.directory}/generated-sources/ci-environments/java io/cucumber/cienvironment diff --git a/java/src/codegen/java/Generate.java b/java/src/codegen/java/io/cucumber/cienvironment/Generate.java similarity index 98% rename from java/src/codegen/java/Generate.java rename to java/src/codegen/java/io/cucumber/cienvironment/Generate.java index 9f0cd540..5efb03a4 100644 --- a/java/src/codegen/java/Generate.java +++ b/java/src/codegen/java/io/cucumber/cienvironment/Generate.java @@ -1,3 +1,5 @@ +package io.cucumber.cienvironment; + import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import freemarker.template.Configuration; diff --git a/java/src/codegen/resources/templates/ci-environments.java.ftl b/java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl similarity index 100% rename from java/src/codegen/resources/templates/ci-environments.java.ftl rename to java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl diff --git a/java/src/main/java/io/cucumber/cienvironment/CiEnvironmentImpl.java b/java/src/main/java/io/cucumber/cienvironment/CiEnvironmentImpl.java index b95bb812..f5501692 100644 --- a/java/src/main/java/io/cucumber/cienvironment/CiEnvironmentImpl.java +++ b/java/src/main/java/io/cucumber/cienvironment/CiEnvironmentImpl.java @@ -1,5 +1,7 @@ package io.cucumber.cienvironment; +import org.jspecify.annotations.Nullable; + import java.util.Objects; import java.util.Optional; @@ -7,12 +9,12 @@ import static java.util.Optional.ofNullable; final class CiEnvironmentImpl implements CiEnvironment { - public String name; - public String url; - public String buildNumber; - public Git git; + private final String name; + private final String url; + private final @Nullable String buildNumber; + private final @Nullable Git git; - CiEnvironmentImpl(String name, String url, String buildNumber, Git git) { + CiEnvironmentImpl(String name, String url, @Nullable String buildNumber, @Nullable Git git) { this.name = requireNonNull(name); this.url = requireNonNull(url); this.buildNumber = buildNumber; @@ -63,12 +65,12 @@ public String toString() { } final static class Git implements CiEnvironment.Git { - public String remote; - public String revision; - public String branch; - public String tag; + private final String remote; + private final String revision; + private final @Nullable String branch; + private final @Nullable String tag; - Git(String remote, String revision, String branch, String tag) { + Git(String remote, String revision, @Nullable String branch, @Nullable String tag) { this.remote = requireNonNull(remote); this.revision = requireNonNull(revision); this.branch = branch; diff --git a/java/src/main/java/io/cucumber/cienvironment/DetectCiEnvironment.java b/java/src/main/java/io/cucumber/cienvironment/DetectCiEnvironment.java index e62225ac..2ca27e6f 100644 --- a/java/src/main/java/io/cucumber/cienvironment/DetectCiEnvironment.java +++ b/java/src/main/java/io/cucumber/cienvironment/DetectCiEnvironment.java @@ -1,11 +1,11 @@ package io.cucumber.cienvironment; +import org.jspecify.annotations.Nullable; + import java.util.Map; import java.util.Optional; import static io.cucumber.cienvironment.VariableExpression.evaluate; -import static java.util.Optional.empty; -import static java.util.Optional.of; public final class DetectCiEnvironment { private DetectCiEnvironment() { @@ -28,9 +28,9 @@ public static Optional detectCiEnvironment(Map en private static Optional detect(CiEnvironment ci, Map env) { String url = evaluate(ci.getUrl(), env); - if (url == null) return empty(); + if (url == null) return Optional.empty(); - return of(new CiEnvironmentImpl( + return Optional.of(new CiEnvironmentImpl( ci.getName(), url, ci.getBuildNumber().map(buildNumber -> evaluate(buildNumber, env)).orElse(null), @@ -38,7 +38,7 @@ private static Optional detect(CiEnvironment ci, Map env) { + private static CiEnvironmentImpl.@Nullable Git detectGit(CiEnvironment ci, Map env) { String revision = evaluateRevision(ci, env); if (revision == null) return null; @@ -58,7 +58,7 @@ private static CiEnvironmentImpl.Git detectGit(CiEnvironment ci, Map env) { + private static @Nullable String evaluateRevision(CiEnvironment ci, Map env) { String revision = GithubEventParser.evaluateRevisionGithub(env); if (revision != null) return revision; return ci.getGit().map(git -> evaluate(git.getRevision(), env)).orElse(null); diff --git a/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java b/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java index d24276e6..6b231ac8 100644 --- a/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java +++ b/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java @@ -1,8 +1,9 @@ package io.cucumber.cienvironment; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; import java.util.regex.Matcher; @@ -19,16 +20,16 @@ final class GithubEventParser { * * https://github.com/orgs/community/discussions/26325 * * https://github.com/cucumber/ci-environment/issues/86 */ - static String evaluateRevisionGithub(Map env) { + static @Nullable String evaluateRevisionGithub(Map env) { if (!"pull_request".equals(env.get("GITHUB_EVENT_NAME"))) { return null; } - if (env.get("GITHUB_EVENT_PATH") == null) { + String path = env.get("GITHUB_EVENT_PATH"); + if (path == null) { return null; } try { - Path path = Paths.get(env.get("GITHUB_EVENT_PATH")); - String event = String.join(" ", Files.readAllLines(path)); + String event = String.join(" ", Files.readAllLines(Paths.get(path))); return parsePullRequestHeadSha(event); } catch (IOException e) { return null; @@ -67,7 +68,7 @@ static String evaluateRevisionGithub(Map env) { // End of object "}$"); - static String parsePullRequestHeadSha(String eventJson) { + static @Nullable String parsePullRequestHeadSha(String eventJson) { // Parse json using regex. Not ideal but works for the limited input. Matcher matcher = GITHUB_EVENT_PATTERN.matcher(eventJson.trim()); if (!matcher.matches()) { diff --git a/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java b/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java index 229d0fd7..4f843e13 100644 --- a/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java +++ b/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java @@ -4,8 +4,8 @@ import java.net.URISyntaxException; final class RemoveUserInfo { + static String fromUrl(String value) { - if (value == null) return null; try { URI uri = URI.create(value); return new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()).toASCIIString(); diff --git a/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java b/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java index d23ffe7e..f243b316 100644 --- a/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java +++ b/java/src/main/java/io/cucumber/cienvironment/VariableExpression.java @@ -1,5 +1,7 @@ package io.cucumber.cienvironment; +import org.jspecify.annotations.Nullable; + import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -13,7 +15,7 @@ private VariableExpression() { } - static String evaluate(String expression, Map env) { + static @Nullable String evaluate(@Nullable String expression, Map env) { if (expression == null) return null; Matcher variableMatcher = variablePattern.matcher(expression); StringBuilder sb = new StringBuilder(); @@ -43,7 +45,7 @@ static String evaluate(String expression, Map env) { return sb.toString(); } - private static String getValue(Map env, String variable) { + private static @Nullable String getValue(Map env, String variable) { if (variable.contains("*")) { Pattern pattern = Pattern.compile(variable.replace("*", ".*")); // GoCD env var with dynamic "material" name diff --git a/java/src/main/java/io/cucumber/cienvironment/package-info.java b/java/src/main/java/io/cucumber/cienvironment/package-info.java new file mode 100644 index 00000000..a5a6f44b --- /dev/null +++ b/java/src/main/java/io/cucumber/cienvironment/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package io.cucumber.cienvironment; + +import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/java/src/test/java/io/cucumber/cienvironment/DetectCiEnvironmentTest.java b/java/src/test/java/io/cucumber/cienvironment/DetectCiEnvironmentTest.java index c9f85d23..7af896f5 100644 --- a/java/src/test/java/io/cucumber/cienvironment/DetectCiEnvironmentTest.java +++ b/java/src/test/java/io/cucumber/cienvironment/DetectCiEnvironmentTest.java @@ -1,7 +1,6 @@ package io.cucumber.cienvironment; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ArgumentConversionException; @@ -30,7 +29,7 @@ class DetectCiEnvironmentTest { - private static List acceptance_tests_pass() throws IOException { + static List acceptance_tests_pass() throws IOException { List paths = new ArrayList<>(); try (DirectoryStream testdata = newDirectoryStream(Paths.get("..", "testdata", "src"), "*.txt")){ testdata.forEach(paths::add); @@ -62,14 +61,18 @@ public CiEnvironment getExpected() { static class Converter implements ArgumentConverter { @Override - public Expectation convert(Object source, ParameterContext context) throws ArgumentConversionException { + public Expectation convert(@Nullable Object source, @Nullable ParameterContext context) throws ArgumentConversionException { + if (source == null) { + throw new ArgumentConversionException("Could not convert null"); + } + Path path = (Path) source; Map env = new HashMap<>(); try (BufferedReader in = newBufferedReader(path)){ String line; while ((line = in.readLine()) != null) { - String[] parts = line.split("="); + String[] parts = line.split("=", 2); if (parts.length == 1) { env.put(parts[0], ""); diff --git a/java/src/test/java/io/cucumber/cienvironment/GitHubPullRequestIntegrationTest.java b/java/src/test/java/io/cucumber/cienvironment/GitHubPullRequestIntegrationTest.java index 32765a5a..9e023715 100644 --- a/java/src/test/java/io/cucumber/cienvironment/GitHubPullRequestIntegrationTest.java +++ b/java/src/test/java/io/cucumber/cienvironment/GitHubPullRequestIntegrationTest.java @@ -9,6 +9,7 @@ import java.util.Map; import static io.cucumber.cienvironment.DetectCiEnvironment.detectCiEnvironment; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.assertEquals; class GitHubPullRequestIntegrationTest { @@ -28,7 +29,8 @@ private static String parseRevisionWithRegularExpression(Map env } private static String parsePullRequestHeadShaWithJackson(Map env) throws IOException { - File file = new File(env.get("GITHUB_EVENT_PATH")); + String githubEventPath = requireNonNull(env.get("GITHUB_EVENT_PATH")); + File file = new File(githubEventPath); JsonNode event = Jackson.OBJECT_MAPPER.readTree(file); return event.get("pull_request").get("head").get("sha").textValue(); } diff --git a/java/src/test/java/io/cucumber/cienvironment/RemoveUserInfoTest.java b/java/src/test/java/io/cucumber/cienvironment/RemoveUserInfoTest.java index 7c5c0c24..a5ccff85 100644 --- a/java/src/test/java/io/cucumber/cienvironment/RemoveUserInfoTest.java +++ b/java/src/test/java/io/cucumber/cienvironment/RemoveUserInfoTest.java @@ -3,13 +3,8 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; class RemoveUserInfoTest { - @Test - void returns_null_for_null() { - assertNull(RemoveUserInfo.fromUrl(null)); - } @Test void returns_empty_string_for_empty_string() { diff --git a/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java b/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java index 88c127d9..20c82f4d 100644 --- a/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java +++ b/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java @@ -2,7 +2,8 @@ import org.junit.jupiter.api.Test; -import java.util.HashMap; +import java.util.Collections; +import java.util.Map; import static io.cucumber.cienvironment.VariableExpression.evaluate; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -12,61 +13,53 @@ public class VariableExpressionTest { @Test public void it_returns_null_when_a_variable_is_undefined() { String expression = "hello-${SOME_VAR}"; - String result = evaluate(expression, new HashMap<>()); + String result = evaluate(expression, Collections.emptyMap()); assertNull(result); } @Test public void it_gets_a_value_without_replacement() { String expression = "${SOME_VAR}"; - String result = evaluate(expression, new HashMap() {{ - put("SOME_VAR", "some_value"); - }}); + String result = evaluate(expression, Map.of("SOME_VAR", "some_value")); assertEquals("some_value", result); } @Test public void it_escapes_a_value_without_replacement() { String expression = "${SOME_VAR}"; - String result = evaluate(expression, new HashMap() {{ - put("SOME_VAR", "${SOME_VAR}"); - }}); + String result = evaluate(expression, Map.of("SOME_VAR", "${SOME_VAR}")); assertEquals("${SOME_VAR}", result); } @Test public void it_captures_a_group() { String expression = "${SOME_REF/refs\\/heads\\/(.*)/\\1}"; - String result = evaluate(expression, new HashMap() {{ - put("SOME_REF", "refs/heads/main"); - }}); + String result = evaluate(expression, Map.of("SOME_REF", "refs/heads/main")); assertEquals("main", result); } @Test public void it_works_with_star_wildcard_in_var() { String expression = "${GO_SCM_*_PR_BRANCH/.*:(.*)/\\1}"; - String result = evaluate(expression, new HashMap() {{ - put("GO_SCM_MY_MATERIAL_PR_BRANCH", "ashwankthkumar:feature-1"); - }}); + String result = evaluate(expression, Map.of("GO_SCM_MY_MATERIAL_PR_BRANCH", "ashwankthkumar:feature-1")); assertEquals("feature-1", result); } @Test public void it_evaluates_a_complex_expression() { String expression = "hello-${VAR1}-${VAR2/(.*) (.*)/\\2-\\1}-world"; - String result = evaluate(expression, new HashMap() {{ - put("VAR1", "amazing"); - put("VAR2", "gorgeous beautiful"); - }}); + String result = evaluate(expression, Map.of( + "VAR1", "amazing", + "VAR2", "gorgeous beautiful" + )); assertEquals("hello-amazing-beautiful-gorgeous-world", result); } @Test public void it_escapes_a_complex_expression() { String expression = "hello-${VAR1}-${VAR2/(.*) (.*)/\\2-\\1}-world"; - String result = evaluate(expression, new HashMap() {{ - put("VAR1", "${VAR1}"); - put("VAR2", "${VAR2a} ${VAR2b}"); - }}); + String result = evaluate(expression, Map.of( + "VAR1", "${VAR1}", + "VAR2", "${VAR2a} ${VAR2b}" + )); assertEquals("hello-${VAR1}-${VAR2b}-${VAR2a}-world", result); } } From 44cbbb4932fe53c877f3e69f26fe9f9d8054c6aa Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Mon, 10 Nov 2025 22:39:32 +0100 Subject: [PATCH 4/7] Enable Checkstyle --- java/pom.xml | 13 +++++++++++++ .../templates/ci-environments.java.ftl | 6 +++++- .../io/cucumber/cienvironment/CiEnvironment.java | 6 ++++++ .../cucumber/cienvironment/GithubEventParser.java | 6 +++++- .../io/cucumber/cienvironment/RemoveUserInfo.java | 4 ++++ .../test/java/io/cucumber/CiEnvironmentExample.java | 9 ++++++--- .../cienvironment/VariableExpressionTest.java | 6 ++++-- 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index 36d01552..623ab2ce 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -176,6 +176,19 @@ + + org.apache.maven.plugins + maven-checkstyle-plugin + + + validate + verify + + check + + + + diff --git a/java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl b/java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl index 7400072f..1bbd4f1b 100644 --- a/java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl +++ b/java/src/codegen/resources/io/cucumber/cienvironment/templates/ci-environments.java.ftl @@ -4,7 +4,7 @@ import java.util.Collection; import static java.util.Arrays.asList; -class CiEnvironments { +final class CiEnvironments { static final Collection TEMPLATES = asList( <#list ciEnvironments as ciEnvironment> new CiEnvironmentImpl( @@ -20,4 +20,8 @@ class CiEnvironments { ); + + private CiEnvironments(){ + // Utility class + } } diff --git a/java/src/main/java/io/cucumber/cienvironment/CiEnvironment.java b/java/src/main/java/io/cucumber/cienvironment/CiEnvironment.java index 3ff176d6..816aa05f 100644 --- a/java/src/main/java/io/cucumber/cienvironment/CiEnvironment.java +++ b/java/src/main/java/io/cucumber/cienvironment/CiEnvironment.java @@ -4,14 +4,20 @@ public interface CiEnvironment { String getName(); + String getUrl(); + Optional getBuildNumber(); + Optional getGit(); interface Git { String getRemote(); + String getRevision(); + Optional getBranch(); + Optional getTag(); } } diff --git a/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java b/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java index 6b231ac8..83382b3a 100644 --- a/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java +++ b/java/src/main/java/io/cucumber/cienvironment/GithubEventParser.java @@ -10,7 +10,11 @@ import java.util.regex.Pattern; final class GithubEventParser { - + + private GithubEventParser(){ + // Utility class + } + /* * Evaluate the current revision on GitHub. * diff --git a/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java b/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java index 4f843e13..e0a80091 100644 --- a/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java +++ b/java/src/main/java/io/cucumber/cienvironment/RemoveUserInfo.java @@ -5,6 +5,10 @@ final class RemoveUserInfo { + private RemoveUserInfo(){ + // Utility class + } + static String fromUrl(String value) { try { URI uri = URI.create(value); diff --git a/java/src/test/java/io/cucumber/CiEnvironmentExample.java b/java/src/test/java/io/cucumber/CiEnvironmentExample.java index 6c333894..01ec3fc3 100644 --- a/java/src/test/java/io/cucumber/CiEnvironmentExample.java +++ b/java/src/test/java/io/cucumber/CiEnvironmentExample.java @@ -2,11 +2,14 @@ import io.cucumber.cienvironment.CiEnvironment; -import java.util.Optional; - import static io.cucumber.cienvironment.DetectCiEnvironment.detectCiEnvironment; -public class CiEnvironmentExample { +public final class CiEnvironmentExample { + + private CiEnvironmentExample(){ + // Demo + } + public static void main(String[] args) { CiEnvironment ciEnvironment = detectCiEnvironment(System.getenv()).orElseThrow(() -> new RuntimeException("No CI environment detected")); System.out.println("ciEnvironment = " + ciEnvironment); diff --git a/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java b/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java index 20c82f4d..649bc958 100644 --- a/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java +++ b/java/src/test/java/io/cucumber/cienvironment/VariableExpressionTest.java @@ -23,6 +23,7 @@ public void it_gets_a_value_without_replacement() { String result = evaluate(expression, Map.of("SOME_VAR", "some_value")); assertEquals("some_value", result); } + @Test public void it_escapes_a_value_without_replacement() { String expression = "${SOME_VAR}"; @@ -53,12 +54,13 @@ public void it_evaluates_a_complex_expression() { )); assertEquals("hello-amazing-beautiful-gorgeous-world", result); } + @Test public void it_escapes_a_complex_expression() { String expression = "hello-${VAR1}-${VAR2/(.*) (.*)/\\2-\\1}-world"; String result = evaluate(expression, Map.of( - "VAR1", "${VAR1}", - "VAR2", "${VAR2a} ${VAR2b}" + "VAR1", "${VAR1}", + "VAR2", "${VAR2a} ${VAR2b}" )); assertEquals("hello-${VAR1}-${VAR2b}-${VAR2a}-world", result); } From 483a6485448f4201b12701e9d537dd5ed70ecbcb Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Thu, 13 Nov 2025 23:28:45 +0100 Subject: [PATCH 5/7] Run checkstyle in validate phase --- java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/pom.xml b/java/pom.xml index 623ab2ce..517acc41 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -182,7 +182,7 @@ validate - verify + validate check From a16626899c9ea916acc43d83fef93265b52b2954 Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Fri, 14 Nov 2025 01:16:42 +0100 Subject: [PATCH 6/7] Setup parent pom and checkstyle --- java/.mvn/jvm.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/.mvn/jvm.config b/java/.mvn/jvm.config index 8488a4fc..32599cef 100644 --- a/java/.mvn/jvm.config +++ b/java/.mvn/jvm.config @@ -7,4 +7,4 @@ --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ---add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ No newline at end of file +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED From db44b50b58537fcb1841acff8330e34eddb8fe8b Mon Sep 17 00:00:00 2001 From: "M.P. Korstanje" Date: Sat, 15 Nov 2025 00:27:12 +0100 Subject: [PATCH 7/7] Update versions and polish --- java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/pom.xml b/java/pom.xml index 517acc41..0de9beb1 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -10,7 +10,7 @@ ci-environment - 12.0.1-SNAPSHOT + 13.0.0-SNAPSHOT jar Cucumber CiEnvironment Detect CI Environment from environment variables