From 13d17b3d3c3da6e3b80315c3d22f2eeaf8c821cd Mon Sep 17 00:00:00 2001 From: Mykola Rybak Date: Fri, 29 Aug 2025 15:02:40 +0300 Subject: [PATCH 1/9] Support keys and configs in SplitClientForTest SplitClientForTest can be useful for unit-testing code that depends on SplitClient, especially in dynamic scenarios where a static config per test class won't work. As of now, SplitClientForTest doesn't support customization of split keys or configs - it always returns the same treatment for all keys of a feature flag and always returns null as a split config. This change extends SplitClientForTest, so it's possible to set treatments for each feature flag and key, and also possible to set split config in addition to the treatment name. --- .../client/testing/SplitClientForTest.java | 120 ++++++++---------- 1 file changed, 54 insertions(+), 66 deletions(-) diff --git a/testing/src/main/java/io/split/client/testing/SplitClientForTest.java b/testing/src/main/java/io/split/client/testing/SplitClientForTest.java index 9ee4b8c3e..124adba0d 100644 --- a/testing/src/main/java/io/split/client/testing/SplitClientForTest.java +++ b/testing/src/main/java/io/split/client/testing/SplitClientForTest.java @@ -1,5 +1,6 @@ package io.split.client.testing; +import io.split.client.SplitAndKey; import io.split.client.SplitClient; import io.split.client.api.Key; import io.split.client.api.SplitResult; @@ -10,130 +11,117 @@ import java.util.concurrent.TimeoutException; public class SplitClientForTest implements SplitClient { - private Map _tests; + private static final SplitResult CONTROL_RESULT = new SplitResult(Treatments.CONTROL, null); + + private Map _tests; public SplitClientForTest() { _tests = new HashMap<>(); } - public Map tests() { + public Map tests() { return _tests; } public void clearTreatments() { - _tests = new HashMap<>(); + _tests.clear(); } public void registerTreatments(Map treatments) { - _tests.putAll(treatments); + for (Map.Entry entry : treatments.entrySet()) { + registerTreatment(entry.getKey(), entry.getValue()); + } } public void registerTreatment(String feature, String treatment) { - _tests.put(feature, treatment); + registerTreatment(feature, null, treatment); + } + + public void registerTreatment(String feature, String key, String treatment) { + registerTreatment(feature, key, treatment, null); + } + + public void registerTreatment(String feature, String key, String treatment, String config) { + registerTreatment(SplitAndKey.of(feature, key), new SplitResult(treatment, config)); + } + + public void registerTreatment(SplitAndKey splitAndKey, SplitResult splitResult) { + _tests.put(splitAndKey, splitResult); } public String getTreatment(String key, String featureFlagName) { - return _tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL; + return getTreatment(key, featureFlagName, Collections.emptyMap()); } public String getTreatment(String key, String featureFlagName, Map attributes) { - return _tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL; + return getTreatmentWithConfig(key, featureFlagName, attributes).treatment(); } public String getTreatment(Key key, String featureFlagName, Map attributes) { - return _tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL; + return getTreatment(key.matchingKey(), featureFlagName, attributes); } @Override public SplitResult getTreatmentWithConfig(String key, String featureFlagName) { - return new SplitResult(_tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL, null); + return getTreatmentWithConfig(key, featureFlagName, Collections.emptyMap()); } @Override public SplitResult getTreatmentWithConfig(String key, String featureFlagName, Map attributes) { - return new SplitResult(_tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL, null); + if (_tests.containsKey(SplitAndKey.of(featureFlagName, key))) { + return _tests.get(SplitAndKey.of(featureFlagName, key)); + } + else { + return _tests.getOrDefault(SplitAndKey.of(featureFlagName), CONTROL_RESULT); + } } @Override public SplitResult getTreatmentWithConfig(Key key, String featureFlagName, Map attributes) { - return new SplitResult(_tests.containsKey(featureFlagName) - ? _tests.get(featureFlagName) - : Treatments.CONTROL, null); + return getTreatmentWithConfig(key.matchingKey(), featureFlagName, attributes); } @Override public Map getTreatments(String key, List featureFlagNames) { - Map treatments = new HashMap<>(); - for (String split : featureFlagNames) { - treatments.put(split, _tests.containsKey(split) ? _tests.get(split) : Treatments.CONTROL); - } - return treatments; + return getTreatments(key, featureFlagNames, Collections.emptyMap()); } @Override public Map getTreatments(String key, List featureFlagNames, Map attributes){ Map treatments = new HashMap<>(); for (String split : featureFlagNames) { - treatments.put(split, _tests.containsKey(split) ? _tests.get(split) : Treatments.CONTROL); + treatments.put(split, getTreatment(key, split, attributes)); } return treatments; } @Override public Map getTreatments(Key key, List featureFlagNames, Map attributes) { - Map treatments = new HashMap<>(); - for (String split : featureFlagNames) { - treatments.put(split, _tests.containsKey(split) ? _tests.get(split) : Treatments.CONTROL); - } - return treatments; + return getTreatments(key.matchingKey(), featureFlagNames, attributes); } @Override public Map getTreatmentsWithConfig(String key, List featureFlagNames) { - Map treatments = new HashMap<>(); - for (String split : featureFlagNames) { - treatments.put(split, new SplitResult(_tests.containsKey(split) - ? _tests.get(split) - : Treatments.CONTROL, null)); - } - return treatments; + return getTreatmentsWithConfig(key, featureFlagNames, Collections.emptyMap()); } @Override public Map getTreatmentsWithConfig(String key, List featureFlagNames, Map attributes) { Map treatments = new HashMap<>(); for (String split : featureFlagNames) { - treatments.put(split, new SplitResult(_tests.containsKey(split) - ? _tests.get(split) - : Treatments.CONTROL, null)); + treatments.put(split, getTreatmentWithConfig(key, split, attributes)); } return treatments; } @Override public Map getTreatmentsWithConfig(Key key, List featureFlagNames, Map attributes) { - Map treatments = new HashMap<>(); - for (String split : featureFlagNames) { - treatments.put(split, new SplitResult(_tests.containsKey(split) - ? _tests.get(split) - : Treatments.CONTROL, null)); - } - return treatments; + return getTreatmentsWithConfig(key.matchingKey(), featureFlagNames, attributes); } @Override public Map getTreatmentsByFlagSet(String key, String flagSet) { - return null; + return new HashMap<>(); } @Override @@ -148,7 +136,7 @@ public Map getTreatmentsByFlagSet(Key key, String flagSet, Map getTreatmentsByFlagSets(String key, List flagSets) { - return null; + return new HashMap<>(); } @Override @@ -163,7 +151,7 @@ public Map getTreatmentsByFlagSets(Key key, List flagSet @Override public Map getTreatmentsWithConfigByFlagSet(String key, String flagSet) { - return null; + return new HashMap<>(); } @Override @@ -178,7 +166,7 @@ public Map getTreatmentsWithConfigByFlagSet(Key key, String @Override public Map getTreatmentsWithConfigByFlagSets(String key, List flagSets) { - return null; + return new HashMap<>(); } @Override @@ -193,62 +181,62 @@ public Map getTreatmentsWithConfigByFlagSets(Key key, List< @Override public String getTreatment(String key, String featureFlagName, EvaluationOptions evaluationOptions) { - return null; + return getTreatment(key, featureFlagName); } @Override public String getTreatment(String key, String featureFlagName, Map attributes, EvaluationOptions evaluationOptions) { - return null; + return getTreatment(key, featureFlagName, attributes); } @Override public String getTreatment(Key key, String featureFlagName, Map attributes, EvaluationOptions evaluationOptions) { - return null; + return getTreatment(key, featureFlagName, attributes); } @Override public Map getTreatments(String key, List featureFlagNames, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatments(key, featureFlagNames); } @Override public Map getTreatments(String key, List featureFlagNames, Map attributes, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatments(key, featureFlagNames, attributes); } @Override public Map getTreatments(Key key, List featureFlagNames, Map attributes, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatments(key, featureFlagNames, attributes); } @Override public SplitResult getTreatmentWithConfig(String key, String featureFlagName, EvaluationOptions evaluationOptions) { - return null; + return getTreatmentWithConfig(key, featureFlagName); } @Override public SplitResult getTreatmentWithConfig(Key key, String featureFlagName, Map attributes, EvaluationOptions evaluationOptions) { - return null; + return getTreatmentWithConfig(key, featureFlagName, attributes); } @Override public SplitResult getTreatmentWithConfig(String key, String featureFlagName, Map attributes, EvaluationOptions evaluationOptions) { - return null; + return getTreatmentWithConfig(key, featureFlagName, attributes); } @Override public Map getTreatmentsWithConfig(String key, List featureFlagNames, Map attributes, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatmentsWithConfig(key, featureFlagNames, attributes); } @Override public Map getTreatmentsWithConfig(String key, List featureFlagNames, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatmentsWithConfig(key, featureFlagNames); } @Override From 2d7c67dd767a9f3211a9c568878040a4622f1d31 Mon Sep 17 00:00:00 2001 From: Mykola Rybak Date: Sat, 4 Apr 2026 01:17:40 +0300 Subject: [PATCH 2/9] Fix SplitClientForTest compatibility Fix compatibility for the SplitClientForTest.tests() method. Keep it with the old signature, expose new complete mappings via testMappings() method. --- .../client/testing/SplitClientForTest.java | 21 +++++++-- .../client/testing/runner/RunWithSplits.java | 10 +++-- .../testing/SplitScenarioAnnotationTest.java | 45 ++++++++++--------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/testing/src/main/java/io/split/client/testing/SplitClientForTest.java b/testing/src/main/java/io/split/client/testing/SplitClientForTest.java index 124adba0d..763d4df5b 100644 --- a/testing/src/main/java/io/split/client/testing/SplitClientForTest.java +++ b/testing/src/main/java/io/split/client/testing/SplitClientForTest.java @@ -10,17 +10,30 @@ import java.util.*; import java.util.concurrent.TimeoutException; +import static java.util.stream.Collectors.toMap; + public class SplitClientForTest implements SplitClient { private static final SplitResult CONTROL_RESULT = new SplitResult(Treatments.CONTROL, null); - private Map _tests; + private final Map _tests; public SplitClientForTest() { _tests = new HashMap<>(); } - public Map tests() { - return _tests; + public Map tests() { + return _tests + .entrySet() + .stream() + .collect(toMap( + entry -> entry.getKey().split(), + entry -> entry.getValue().treatment(), + (existing, replacement) -> existing + )); + } + + public Map testMappings() { + return Collections.unmodifiableMap(_tests); } public void clearTreatments() { @@ -286,7 +299,7 @@ public Map getTreatmentsByFlagSet(String key, String flagSet, Ev @Override public Map getTreatmentsWithConfig(Key key, List featureFlagNames, Map attributes, EvaluationOptions evaluationOptions) { - return new HashMap<>(); + return getTreatmentsWithConfig(key.matchingKey(), featureFlagNames); } @Override diff --git a/testing/src/main/java/io/split/client/testing/runner/RunWithSplits.java b/testing/src/main/java/io/split/client/testing/runner/RunWithSplits.java index d6b864ad4..01c6d3ee3 100644 --- a/testing/src/main/java/io/split/client/testing/runner/RunWithSplits.java +++ b/testing/src/main/java/io/split/client/testing/runner/RunWithSplits.java @@ -1,5 +1,7 @@ package io.split.client.testing.runner; +import io.split.client.SplitAndKey; +import io.split.client.api.SplitResult; import io.split.client.testing.SplitClientForTest; import io.split.client.testing.annotations.SplitTestClient; import org.junit.runners.model.Statement; @@ -24,7 +26,7 @@ public void evaluate() throws Throwable { SplitClientForTest splitClient = findFirstSplitClient(target, target.getClass()); // Preserve the Split state between Test runs - Map priorTests = new HashMap<>(splitClient.tests()); + Map priorTests = new HashMap<>(splitClient.testMappings()); // Apply the Active Scenario for this if (scenario != null) { @@ -36,7 +38,9 @@ public void evaluate() throws Throwable { } finally { // Clear any Scenario specific changes and re-apply existing splits splitClient.clearTreatments(); - splitClient.registerTreatments(priorTests); + for (Map.Entry entry : priorTests.entrySet()) { + splitClient.registerTreatment(entry.getKey(), entry.getValue()); + } } } @@ -57,4 +61,4 @@ private static SplitClientForTest findFirstSplitClient(Object target, Class t throw new IllegalArgumentException("No SplitTestClient found in hierarchy"); } } -} \ No newline at end of file +} diff --git a/testing/src/test/java/io/split/client/testing/SplitScenarioAnnotationTest.java b/testing/src/test/java/io/split/client/testing/SplitScenarioAnnotationTest.java index 84a772ceb..f590d0c5d 100644 --- a/testing/src/test/java/io/split/client/testing/SplitScenarioAnnotationTest.java +++ b/testing/src/test/java/io/split/client/testing/SplitScenarioAnnotationTest.java @@ -1,6 +1,8 @@ package io.split.client.testing; +import com.google.common.collect.ImmutableMap; import io.split.client.api.Key; +import io.split.client.api.SplitResult; import io.split.client.dtos.EvaluationOptions; import io.split.client.testing.annotations.SplitScenario; import io.split.client.testing.annotations.SplitSuite; @@ -12,7 +14,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Objects; @@ -78,29 +79,29 @@ public void testDefaultScenario() { Assert.assertEquals(CONTROL_TREATMENT, splitClient.getTreatment(ARBITRARY_KEY, CONTROL_FEATURE)); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset", new HashMap<>())); - Assert.assertEquals(null, splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset")); - Assert.assertEquals(null, splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset")); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset")); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset")); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"), new HashMap<>())); - Assert.assertEquals(null, splitClient.getTreatmentsByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); - Assert.assertEquals(null, splitClient.getTreatmentsByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSet(ARBITRARY_KEY, "flagset", new HashMap<>())); - Assert.assertEquals(null, splitClient.getTreatmentsWithConfigByFlagSet(ARBITRARY_KEY, "flagset")); - Assert.assertEquals(null, splitClient.getTreatmentsWithConfigByFlagSet(ARBITRARY_KEY, "flagset")); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSet(ARBITRARY_KEY, "flagset")); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSet(ARBITRARY_KEY, "flagset")); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"), new HashMap<>())); - Assert.assertEquals(null, splitClient.getTreatmentsWithConfigByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); - Assert.assertEquals(null, splitClient.getTreatmentsWithConfigByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); - - Assert.assertEquals(null, splitClient.getTreatment(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatment(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatment(new Key(ARBITRARY_KEY, ARBITRARY_KEY), DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatmentWithConfig(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatmentWithConfig(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatmentWithConfig(new Key(ARBITRARY_KEY, ARBITRARY_KEY), DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(new HashMap<>(), splitClient.getTreatments(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(new HashMap<>(), splitClient.getTreatments(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfig(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new EvaluationOptions(new HashMap<>()))); - Assert.assertEquals(null, splitClient.getTreatmentsWithConfig(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>())).get(DEFAULT_CLIENT_FEATURE)); - Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfig(new Key(ARBITRARY_KEY, ARBITRARY_KEY), Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); + Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsWithConfigByFlagSets(ARBITRARY_KEY, Arrays.asList("flagset"))); + + Assert.assertEquals(ON_TREATMENT, splitClient.getTreatment(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(ON_TREATMENT, splitClient.getTreatment(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(ON_TREATMENT, splitClient.getTreatment(new Key(ARBITRARY_KEY, ARBITRARY_KEY), DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(new SplitResult(ON_TREATMENT, null), splitClient.getTreatmentWithConfig(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(new SplitResult(ON_TREATMENT, null), splitClient.getTreatmentWithConfig(ARBITRARY_KEY, DEFAULT_CLIENT_FEATURE, new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(new SplitResult(ON_TREATMENT, null), splitClient.getTreatmentWithConfig(new Key(ARBITRARY_KEY, ARBITRARY_KEY), DEFAULT_CLIENT_FEATURE, new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(ImmutableMap.of(DEFAULT_CLIENT_FEATURE, ON_TREATMENT), splitClient.getTreatments(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(ImmutableMap.of(DEFAULT_CLIENT_FEATURE, ON_TREATMENT), splitClient.getTreatments(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(ImmutableMap.of(DEFAULT_CLIENT_FEATURE, new SplitResult(ON_TREATMENT, null)), splitClient.getTreatmentsWithConfig(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new EvaluationOptions(new HashMap<>()))); + Assert.assertEquals(new SplitResult(ON_TREATMENT, null), splitClient.getTreatmentsWithConfig(ARBITRARY_KEY, Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>())).get(DEFAULT_CLIENT_FEATURE)); + Assert.assertEquals(ImmutableMap.of(DEFAULT_CLIENT_FEATURE, new SplitResult(ON_TREATMENT, null)), splitClient.getTreatmentsWithConfig(new Key(ARBITRARY_KEY, ARBITRARY_KEY), Arrays.asList(DEFAULT_CLIENT_FEATURE), new HashMap<>(), new EvaluationOptions(new HashMap<>()))); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset", new HashMap<>(), new EvaluationOptions(new HashMap<>()))); Assert.assertEquals(new HashMap<>(), splitClient.getTreatmentsByFlagSet(ARBITRARY_KEY, "flagset", new EvaluationOptions(new HashMap<>()))); @@ -220,4 +221,4 @@ public void testScenariosAnnotation() { Assert.assertEquals(ON_TREATMENT, splitClient.getTreatment(ARBITRARY_KEY, "SCENARIO_FEATURE_3")); } } -} \ No newline at end of file +} From 3a1a996c5cf33900df9ed201c3191cf42e60872e Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 15:15:51 -0300 Subject: [PATCH 3/9] Added harness ci: --- .../pipelines/java_client_ci.yaml | 109 ++++++++++++++++++ .../java_client_ci/input_sets/pr.yaml | 14 +++ .../java_client_ci/input_sets/push.yaml | 14 +++ 3 files changed, 137 insertions(+) create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/pr.yaml create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/push.yaml diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml new file mode 100644 index 000000000..509837c2e --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml @@ -0,0 +1,109 @@ +pipeline: + name: java-client-ci + identifier: java_client_ci + projectIdentifier: Harness_Split + orgIdentifier: PROD + tags: {} + properties: + ci: + codebase: + connectorRef: fmegithubrunnersci + repoName: java-client + build: <+input> + depth: 0 + stages: + - stage: + name: test + identifier: test + type: CI + spec: + cloneCodebase: true + caching: + enabled: true + override: true + platform: + os: Linux + arch: Amd64 + runtime: + type: Cloud + spec: {} + execution: + steps: + # JDK 8: build + test + checkstyle (PR only) + - step: + type: Run + name: test jdk8 + identifier: test_jdk8 + spec: + connectorRef: dockerhub + image: maven:3.9-eclipse-temurin-8 + shell: Bash + envVariables: + MAVEN_OPTS: "-XX:InitialHeapSize=2G -XX:MaxHeapSize=2G -XX:+PrintCommandLineFlags -XX:ThreadStackSize=65536 -XX:-TieredCompilation -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" + command: |- + apt-get update -qq && apt-get install -y --no-install-recommends redis-server + redis-server --daemonize yes + for i in $(seq 1 30); do + redis-cli ping 2>/dev/null | grep -q PONG && { echo "Redis is up"; break; } + echo "Waiting for Redis... ($i/30)"; sleep 1 + done + cp .ci.settings.xml ${HOME}/.m2/settings.xml + mvn --batch-mode clean install + when: + stageStatus: Success + condition: <+codebase.build.type> == "PR" + # JDK 8: checkstyle (PR only, runs after build succeeds) + - step: + type: Run + name: checkstyle jdk8 + identifier: checkstyle_jdk8 + spec: + connectorRef: dockerhub + image: maven:3.9-eclipse-temurin-8 + shell: Bash + envVariables: + MAVEN_OPTS: "-XX:InitialHeapSize=2G -XX:MaxHeapSize=2G -XX:+PrintCommandLineFlags -XX:ThreadStackSize=65536 -XX:-TieredCompilation -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" + command: mvn --batch-mode checkstyle:check + when: + stageStatus: Success + condition: <+codebase.build.type> == "PR" + # JDK 11: Sonar (PR and push to master/development) + - step: + type: Run + name: sonar analysis + identifier: sonar_analysis + spec: + connectorRef: dockerhub + image: maven:3.9-eclipse-temurin-11 + shell: Bash + envVariables: + MAVEN_OPTS: "-XX:InitialHeapSize=2G -XX:MaxHeapSize=2G -XX:+PrintCommandLineFlags -XX:ThreadStackSize=65536 -XX:-TieredCompilation -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" + SONAR_HOST_URL: https://sonar.harness.io + SONAR_TOKEN: <+secrets.getValue("sonarqube-token")> + PR_NUMBER: <+trigger.prNumber> + PR_BRANCH: <+trigger.sourceBranch> + PR_BASE_BRANCH: <+trigger.targetBranch> + BRANCH_NAME: <+trigger.branch> + command: |- + apt-get update -qq && apt-get install -y --no-install-recommends redis-server + redis-server --daemonize yes + for i in $(seq 1 30); do + redis-cli ping 2>/dev/null | grep -q PONG && { echo "Redis is up"; break; } + echo "Waiting for Redis... ($i/30)"; sleep 1 + done + cp .ci.settings.xml ${HOME}/.m2/settings.xml + if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then + mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + -Dsonar.host.url="$SONAR_HOST_URL" \ + -Dsonar.token="$SONAR_TOKEN" \ + -Dsonar.pullrequest.key="$PR_NUMBER" \ + -Dsonar.pullrequest.branch="$PR_BRANCH" \ + -Dsonar.pullrequest.base="$PR_BASE_BRANCH" + else + mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + -Dsonar.host.url="$SONAR_HOST_URL" \ + -Dsonar.token="$SONAR_TOKEN" \ + -Dsonar.branch.name="$BRANCH_NAME" + fi + when: + stageStatus: Success diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/pr.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/pr.yaml new file mode 100644 index 000000000..799b2126a --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/pr.yaml @@ -0,0 +1,14 @@ +inputSet: + name: pr + identifier: pr + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: java_client_ci + properties: + ci: + codebase: + build: + type: PR + spec: + number: <+trigger.prNumber> diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/push.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/push.yaml new file mode 100644 index 000000000..58e96c1e4 --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci/input_sets/push.yaml @@ -0,0 +1,14 @@ +inputSet: + name: push + identifier: push + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: java_client_ci + properties: + ci: + codebase: + build: + type: branch + spec: + branch: <+trigger.branch> From 0b22f432d49ec4a898032e32ba5d57e5b941988d Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 17:59:59 -0300 Subject: [PATCH 4/9] trigger CI AI-Session-Id: 53746d45-e1a8-4be9-9ae1-7164847af11c AI-Tool: claude-code AI-Model: unknown From 0ae223828cedc43457ef9b8425e89b7b44db9a3f Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 18:02:04 -0300 Subject: [PATCH 5/9] trigger CI again AI-Session-Id: 53746d45-e1a8-4be9-9ae1-7164847af11c AI-Tool: claude-code AI-Model: unknown From 73a63e85e6ff561a89eee03ea84b55cc44bf713e Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 18:11:08 -0300 Subject: [PATCH 6/9] trigger CI AI-Session-Id: 53746d45-e1a8-4be9-9ae1-7164847af11c AI-Tool: claude-code AI-Model: unknown From e53022f59a6ed68e694596cefa1ca08c59dfb842 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 18:14:46 -0300 Subject: [PATCH 7/9] fix: mkdir .m2 before copying settings.xml AI-Session-Id: 53746d45-e1a8-4be9-9ae1-7164847af11c AI-Tool: claude-code AI-Model: unknown --- .../PROD/projects/Harness_Split/pipelines/java_client_ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml index 509837c2e..771dd50ab 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml @@ -47,7 +47,7 @@ pipeline: redis-cli ping 2>/dev/null | grep -q PONG && { echo "Redis is up"; break; } echo "Waiting for Redis... ($i/30)"; sleep 1 done - cp .ci.settings.xml ${HOME}/.m2/settings.xml + mkdir -p ${HOME}/.m2 && cp .ci.settings.xml ${HOME}/.m2/settings.xml mvn --batch-mode clean install when: stageStatus: Success @@ -91,7 +91,7 @@ pipeline: redis-cli ping 2>/dev/null | grep -q PONG && { echo "Redis is up"; break; } echo "Waiting for Redis... ($i/30)"; sleep 1 done - cp .ci.settings.xml ${HOME}/.m2/settings.xml + mkdir -p ${HOME}/.m2 && cp .ci.settings.xml ${HOME}/.m2/settings.xml if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then mvn --batch-mode clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ -Dsonar.host.url="$SONAR_HOST_URL" \ From 59f491ef76f1c21702d75cab771f2d7c62cc8a77 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 18:38:26 -0300 Subject: [PATCH 8/9] =?UTF-8?q?remove=20GitHub=20Actions=20workflows=20?= =?UTF-8?q?=E2=80=94=20replaced=20by=20Harness=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 79 ----------------------- .github/workflows/update-license-year.yml | 45 ------------- 2 files changed, 124 deletions(-) delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/update-license-year.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index b43f4a5dc..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: ci - -on: - push: - branches: - - '**' - pull_request: - branches: - - master - - development - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - test: - name: Test - runs-on: ubuntu-latest - services: - redis: - image: redis - ports: - - 6379:6379 - strategy: - fail-fast: false - matrix: - jdk: - - '8' - - '11' - - '19' - env: - SONARQUBE_HOST_URL: ${{ vars.SONARQUBE_HOST }} - ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }} - ARTIFACTORY_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - MAVEN_OPTS: "-XX:InitialHeapSize=2G -XX:MaxHeapSize=2G -XX:+PrintCommandLineFlags -XX:ThreadStackSize=65536 -XX:-TieredCompilation -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" - muteProps: "true" - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup JDK ${{ matrix.jdk }} - uses: actions/setup-java@v3 - with: - distribution: 'adopt' - java-version: ${{ matrix.jdk }} - - - name: Setup Maven - run: cp .ci.settings.xml ${HOME}/.m2/settings.xml - - - name: Test - if: matrix.jdk == '8' && github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' - run: mvn --batch-mode clean install - - - name: Linter - if: matrix.jdk == '8' && github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' - run: mvn checkstyle::check - -# - name: Deploy -# if: matrix.jdk == '8' && github.event_name == 'push' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' -# run: mvn --batch-mode deploy -P test - - - name: SonarQube Scan (Push) - if: matrix.jdk == '11' && github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') - run: | - mvn --batch-mode clean verify sonar:sonar \ - -Dsonar.branch.name=${{ github.ref_name }} - - - name: SonarQube Scan (Pull Request) - if: matrix.jdk == '11' && github.event_name == 'pull_request' - run: | - mvn --batch-mode clean verify sonar:sonar \ - -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} \ - -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} \ - -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} diff --git a/.github/workflows/update-license-year.yml b/.github/workflows/update-license-year.yml deleted file mode 100644 index 7e0a945f9..000000000 --- a/.github/workflows/update-license-year.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Update License Year - -on: - schedule: - - cron: "0 3 1 1 *" # 03:00 AM on January 1 - -permissions: - contents: write - pull-requests: write - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set Current year - run: "echo CURRENT=$(date +%Y) >> $GITHUB_ENV" - - - name: Set Previous Year - run: "echo PREVIOUS=$(($CURRENT-1)) >> $GITHUB_ENV" - - - name: Update LICENSE - uses: jacobtomlinson/gha-find-replace@v3 - with: - find: ${{ env.PREVIOUS }} - replace: ${{ env.CURRENT }} - include: "LICENSE" - regex: false - - - name: Commit files - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git commit -m "Updated License Year" -a - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 - with: - token: ${{ secrets.GITHUB_TOKEN }} - title: Update License Year - branch: update-license From 3c0e372d8f7f348cacd384b70eaac6b69f8721d8 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 29 Jul 2026 18:50:58 -0300 Subject: [PATCH 9/9] move linter configs to .harness/linter and remove .github folder AI-Session-Id: 53746d45-e1a8-4be9-9ae1-7164847af11c AI-Tool: claude-code AI-Model: unknown --- .github/CODEOWNERS | 1 - {.github => .harness}/linter/checkstyle-suppressions.xml | 0 {.github => .harness}/linter/google-java-style.xml | 0 .../PROD/projects/Harness_Split/pipelines/java_client_ci.yaml | 2 +- pom.xml | 2 +- 5 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 .github/CODEOWNERS rename {.github => .harness}/linter/checkstyle-suppressions.xml (100%) rename {.github => .harness}/linter/google-java-style.xml (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 9e3198100..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @splitio/sdk diff --git a/.github/linter/checkstyle-suppressions.xml b/.harness/linter/checkstyle-suppressions.xml similarity index 100% rename from .github/linter/checkstyle-suppressions.xml rename to .harness/linter/checkstyle-suppressions.xml diff --git a/.github/linter/google-java-style.xml b/.harness/linter/google-java-style.xml similarity index 100% rename from .github/linter/google-java-style.xml rename to .harness/linter/google-java-style.xml diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml index 771dd50ab..208567715 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/java_client_ci.yaml @@ -52,7 +52,7 @@ pipeline: when: stageStatus: Success condition: <+codebase.build.type> == "PR" - # JDK 8: checkstyle (PR only, runs after build succeeds) + # JDK 8: checkstyle (PR only) - step: type: Run name: checkstyle jdk8 diff --git a/pom.xml b/pom.xml index b388caf0e..271ba1717 100644 --- a/pom.xml +++ b/pom.xml @@ -127,7 +127,7 @@ - .github/linter/google-java-style.xml + .harness/linter/google-java-style.xml warning true