Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/master-2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Master CI v2

on:
push:
branches: [master-2]
pull_request:
branches: [master-2]

jobs:
build-scan:
name: SonarCloud Scan
runs-on: ubuntu-latest
if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
cache: maven

- name: Build/Test & SonarCloud Scan
run: mvn -B clean verify -Pcoverage,sonar -Dsonar.token=${{ secrets.SONAR_TOKEN }}

build-test:
name: Build & Test - JDK ${{ matrix.java }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
java: ['11', '17', '21']
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"

steps:
- uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}

- name: Show Versions
run: mvn -version

- name: Cache Maven packages
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-m2-${{ matrix.java }}
restore-keys: ${{ runner.os }}-m2-

- name: Build/Test
run: mvn -B clean package
2 changes: 0 additions & 2 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ jobs:

- name: Build/Test & SonarCloud Scan
run: mvn -B clean verify -Pcoverage,sonar -Dsonar.token=${{ secrets.SONAR_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build-test:
name: Build & Test - JDK ${{ matrix.java }} on ${{ matrix.os }}
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ switcher.domain -> Domain name
#optional
switcher.environment -> Environment name
switcher.local -> true/false When local, it will only use a local snapshot
switcher.check -> true/false When true, it will check Switcher Keys
switcher.relay.restrict -> true/false When true, it will check snapshot relay status
switcher.snapshot.location -> Folder from where snapshots will be saved/read
switcher.snapshot.auto -> true/false Automated lookup for snapshot when initializing the client
Expand Down Expand Up @@ -314,6 +315,16 @@ void testSwitchers() {
}
```

Alternatively, you can also set the Switcher Context configuration to check during the client initialization.

```java
MyAppFeatures.configure(ContextBuilder.builder()
...
.checkSwitchers(true));

MyAppFeatures.initializeClient();
```

#### SwitcherTest annotation - Requires JUnit 5 Jupiter
Predefine Switchers result outside your test methods with the SwitcherTest annotation.
</br>It encapsulates the test and makes sure that the Switcher returns to its original state after concluding the test.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ public ContextBuilder local(boolean local) {
return this;
}

/**
* @param checkSwitchers true/false When true, it will check switcher keys
* @return ContextBuilder
*/
public ContextBuilder checkSwitchers(boolean checkSwitchers) {
switcherProperties.setValue(ContextKey.CHECK_SWITCHERS, checkSwitchers);
return this;
}

/**
* @param restrictRelay true/false When true, it will check snapshot relay status
* @return ContextBuilder
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/github/switcherapi/client/SwitcherConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ abstract class SwitcherConfig {
protected String environment;

protected boolean local;
protected boolean check;
protected String silent;
protected Integer timeout;
protected Integer regexTimeout;
protected Integer poolSize;
protected RelayConfig relay;
protected SnapshotConfig snapshot;
protected TruststoreConfig truststore;

SwitcherConfig() {
this.relay = new RelayConfig();
this.snapshot = new SnapshotConfig();
this.truststore = new TruststoreConfig();
}
Expand All @@ -35,10 +38,15 @@ protected void updateSwitcherConfig(SwitcherProperties properties) {
setComponent(properties.getValue(ContextKey.COMPONENT));
setEnvironment(properties.getValue(ContextKey.ENVIRONMENT));
setLocal(properties.getBoolean(ContextKey.LOCAL_MODE));
setCheck(properties.getBoolean(ContextKey.CHECK_SWITCHERS));
setSilent(properties.getValue(ContextKey.SILENT_MODE));
setTimeout(properties.getInt(ContextKey.TIMEOUT_MS));
setPoolSize(properties.getInt(ContextKey.POOL_CONNECTION_SIZE));

RelayConfig relayConfig = new RelayConfig();
relayConfig.setRestrict(properties.getBoolean(ContextKey.RESTRICT_RELAY));
setRelay(relayConfig);

SnapshotConfig snapshotConfig = new SnapshotConfig();
snapshotConfig.setLocation(properties.getValue(ContextKey.SNAPSHOT_LOCATION));
snapshotConfig.setAuto(properties.getBoolean(ContextKey.SNAPSHOT_AUTO_LOAD));
Expand Down Expand Up @@ -93,6 +101,10 @@ public void setLocal(boolean local) {
this.local = local;
}

public void setCheck(boolean check) {
this.check = check;
}

public void setSilent(String silent) {
this.silent = silent;
}
Expand All @@ -109,6 +121,9 @@ public void setPoolSize(Integer poolSize) {
this.poolSize = poolSize;
}

public void setRelay(RelayConfig relay) {
this.relay = relay;
}
public void setSnapshot(SnapshotConfig snapshot) {
this.snapshot = snapshot;
}
Expand All @@ -117,6 +132,18 @@ public void setTruststore(TruststoreConfig truststore) {
this.truststore = truststore;
}

public static class RelayConfig {
private boolean restrict;

public boolean isRestrict() {
return restrict;
}

public void setRestrict(boolean restrict) {
this.restrict = restrict;
}
}

public static class SnapshotConfig {
private String location;
private boolean auto;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ protected void configureClient() {
.environment(environment)
.component(component)
.local(local)
.checkSwitchers(check)
.restrictRelay(relay.isRestrict())
.silentMode(silent)
.regexTimeout(regexTimeout)
.timeoutMs(timeout)
Expand Down Expand Up @@ -181,7 +183,7 @@ public static void initializeClient() {
validateContext();
registerSwitcherKeys();
switcherExecutor = buildInstance();

loadSwitchers();
scheduleSnapshotAutoUpdate(contextStr(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL));
ContextBuilder.preConfigure(switcherProperties);
Expand Down Expand Up @@ -250,8 +252,14 @@ private static void registerSwitcherKey(Field[] fields) {

/**
* Load Switcher instances into a map cache
*
* @throws SwitchersValidationException if "switcher.check" is enabled and one or more Switcher Keys are not found
*/
private static void loadSwitchers() {
private static void loadSwitchers() throws SwitchersValidationException {
if (contextBol(ContextKey.CHECK_SWITCHERS)) {
checkSwitchers();
}

if (Objects.isNull(switchers)) {
switchers = new HashMap<>();
}
Expand Down Expand Up @@ -447,7 +455,7 @@ public static void stopWatchingSnapshot() {
*
* @throws SwitchersValidationException when one or more Switcher Key is not found
*/
public static void checkSwitchers() {
public static void checkSwitchers() throws SwitchersValidationException {
switcherExecutor.checkSwitchers(switcherKeys);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public SwitcherPropertiesImpl() {
setValue(ContextKey.SNAPSHOT_AUTO_LOAD, false);
setValue(ContextKey.SNAPSHOT_SKIP_VALIDATION, false);
setValue(ContextKey.LOCAL_MODE, false);
setValue(ContextKey.CHECK_SWITCHERS, false);
setValue(ContextKey.RESTRICT_RELAY, true);
}

Expand All @@ -40,6 +41,7 @@ public void loadFromProperties(Properties prop) {
setValue(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL, SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL.getParam(), prop));
setValue(ContextKey.SILENT_MODE, SwitcherUtils.resolveProperties(ContextKey.SILENT_MODE.getParam(), prop));
setValue(ContextKey.LOCAL_MODE, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.LOCAL_MODE.getParam(), prop), false));
setValue(ContextKey.CHECK_SWITCHERS, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.CHECK_SWITCHERS.getParam(), prop), false));
setValue(ContextKey.RESTRICT_RELAY, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.RESTRICT_RELAY.getParam(), prop), true));
setValue(ContextKey.REGEX_TIMEOUT, getIntDefault(SwitcherUtils.resolveProperties(ContextKey.REGEX_TIMEOUT.getParam(), prop), DEFAULT_REGEX_TIMEOUT));
setValue(ContextKey.TRUSTSTORE_PATH, SwitcherUtils.resolveProperties(ContextKey.TRUSTSTORE_PATH.getParam(), prop));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public enum ContextKey {
*/
LOCAL_MODE("switcher.local"),

/**
* (boolean) Defines if client will check the switchers before using them (default is false).
*/
CHECK_SWITCHERS("switcher.check"),

/**
* (boolean) Defines if client will trigger local snapshot relay verification (default is true)
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.github.switcherapi.client.remote.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.switcherapi.client.remote.ClientWS;

import java.util.Arrays;
import java.util.Set;

import com.github.switcherapi.client.remote.ClientWS;

/**
* Request/Response model to use with {@link ClientWS#checkSwitchers(Set, String)}
*
Expand All @@ -21,6 +22,7 @@ public class SwitchersCheck {
/**
* Response field
*/
@JsonProperty("not_found")
private String[] notFound;

public SwitchersCheck() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ static void setup() throws IOException {
MockWebServerHelper.setupMockServer();

Switchers.loadProperties(); // Load default properties from resources
Switchers.initializeClient(); // SwitcherContext requires preload before config override
Switchers.configure(ContextBuilder.builder() // Override default properties
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
.local(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ static void setup() throws IOException {
MockWebServerHelper.setupMockServer();

Switchers.loadProperties(); // Load default properties from resources
Switchers.initializeClient(); // SwitcherContext requires preload before config override
Switchers.configure(ContextBuilder.builder() // Override default properties
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
.local(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ void shouldInitializeClientFromSwitcherConfig_Minimal() {

private <T extends SwitcherConfig> T buildSwitcherClientConfig(T classConfig, String component,
String domain) {
SwitcherConfig.RelayConfig relay = new SwitcherConfig.RelayConfig();
relay.setRestrict(false);

SwitcherConfig.SnapshotConfig snapshot = new SwitcherConfig.SnapshotConfig();
snapshot.setLocation(SNAPSHOTS_LOCAL);
snapshot.setUpdateInterval(null);
Expand All @@ -54,10 +57,12 @@ private <T extends SwitcherConfig> T buildSwitcherClientConfig(T classConfig, St
classConfig.setDomain(domain);
classConfig.setEnvironment("fixture1");
classConfig.setLocal(true);
classConfig.setCheck(false);
classConfig.setSilent("5m");
classConfig.setTimeout(3000);
classConfig.setRegexTimeout(1000);
classConfig.setPoolSize(2);
classConfig.setRelay(relay);
classConfig.setSnapshot(snapshot);
classConfig.setTruststore(truststore);
return classConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ static void setup() throws IOException {
MockWebServerHelper.setupMockServer();

Switchers.loadProperties(); // Load default properties from resources
Switchers.initializeClient(); // SwitcherContext requires preload before config override
Switchers.configure(ContextBuilder.builder() // Override default properties
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
.local(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.github.switcherapi.Switchers;
import com.github.switcherapi.client.ContextBuilder;
import com.github.switcherapi.client.SwitcherContext;
import com.github.switcherapi.client.SwitcherProperties;
import com.github.switcherapi.client.exception.SwitchersValidationException;
import com.github.switcherapi.client.model.SwitcherRequest;
import com.github.switcherapi.client.model.SwitcherResult;
import com.github.switcherapi.client.remote.dto.SwitchersCheck;
Expand All @@ -29,8 +31,7 @@
import java.util.concurrent.Executors;

import static com.github.switcherapi.client.remote.Constants.DEFAULT_TIMEOUT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;

class ClientRemoteTest extends MockWebServerHelper {

Expand Down Expand Up @@ -60,7 +61,7 @@ void resetSwitcherContextState() {
clientRemote = new ClientRemoteService(ClientWSImpl.build(switcherProperties, executorService, DEFAULT_TIMEOUT), switcherProperties);
((QueueDispatcher) mockBackEnd.getDispatcher()).clear();

Switchers.configure(ContextBuilder.builder());
Switchers.configure(ContextBuilder.builder().checkSwitchers(false));
Switchers.initializeClient();
}

Expand All @@ -84,7 +85,7 @@ void shouldExecuteCriteria() {
}

@Test
void shouldCheckSwitchers() {
void shouldCheckSwitchersError() {
//given
final Set<String> switcherKeys = new HashSet<>();
switcherKeys.add("KEY");
Expand All @@ -97,4 +98,30 @@ void shouldCheckSwitchers() {
assertEquals(1, actual.getNotFound().length);
}

@Test
void shouldCheckSwitchersError_throughContextConfiguration() {
//given
final Set<String> switcherKeys = new HashSet<>();
switcherKeys.add("KEY");

givenResponse(generateMockAuth(100));
givenResponse(generateCheckSwitchersResponse(switcherKeys));

//test
Switchers.configure(ContextBuilder.builder().checkSwitchers(true));
SwitchersValidationException exception = assertThrows(SwitchersValidationException.class, SwitcherContext::initializeClient);
assertEquals("Something went wrong: Unable to load the following Switcher Key(s): [KEY]", exception.getMessage());
}

@Test
void shouldCheckSwitchersSuccess_throughContextConfiguration() {
//given
givenResponse(generateMockAuth(100));
givenResponse(generateCheckSwitchersResponse(new HashSet<>()));

//test
Switchers.configure(ContextBuilder.builder().checkSwitchers(true));
assertDoesNotThrow(SwitcherContext::initializeClient);
}

}
Loading