From 106ce9f4ace237642aeb32194172109f8dc452cf Mon Sep 17 00:00:00 2001 From: Tyler Potter Date: Tue, 26 Nov 2024 14:04:49 -0700 Subject: [PATCH 1/8] chore: bump version (#136) --- eppo/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eppo/build.gradle b/eppo/build.gradle index 806bf83..b55d217 100644 --- a/eppo/build.gradle +++ b/eppo/build.gradle @@ -7,7 +7,7 @@ plugins { } group = "cloud.eppo" -version = "4.3.3" +version = "4.3.4-SNAPSNOT" android { buildFeatures.buildConfig true From 5081590425fc55be53d272a8cb4234f4a14e007f Mon Sep 17 00:00:00 2001 From: Tyler Potter Date: Tue, 26 Nov 2024 22:45:51 -0700 Subject: [PATCH 2/8] feat: test status badge on README (#138) * feat: test status badge on README * add maven badge --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8cbfeaf..cf8d8bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Eppo Android SDK +[![Test](https://github.com/Eppo-exp/android-sdk/actions/workflows/test.yaml/badge.svg)](https://github.com/Eppo-exp/android-sdk/actions/workflows/test.yaml) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/cloud.eppo/android-sdk/badge.svg)](https://maven-badges.herokuapp.com/maven-central/cloud.eppo/android-sdk) + [Eppo](https://geteppo.com) is a feature management and experimentation platform. This SDK enables feature flagging and experimentation for Eppo customers. An API key is required to use it. From 080c98af561cdcdd896b4a8515ae031bbc2522b9 Mon Sep 17 00:00:00 2001 From: Tyler Potter Date: Thu, 28 Nov 2024 10:11:32 -0700 Subject: [PATCH 3/8] feat: plumb SDK test data branch through to URL used for test config (#137) * feat: plumb SDK test data branch through to URL used for test config --- .github/workflows/test.yaml | 14 +++++++------- .../java/cloud/eppo/android/EppoClientTest.java | 12 ++++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8f5a946..17c9376 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,8 +21,8 @@ on: required: false env: - SDK_BRANCH_NAME: ${{ inputs.sdk_branch || github.head_ref || github.ref_name }} - TEST_DATA_BRANCH_NAME: ${{ inputs.test_data_branch || 'main' }} + SDK_BRANCH: ${{ inputs.sdk_branch || github.head_ref || github.ref_name }} + TEST_DATA_BRANCH: ${{ inputs.test_data_branch || 'main' }} ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }} ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }} @@ -43,15 +43,15 @@ jobs: - name: Display Testing Details run: | echo "Running SDK Test using" - echo "Test Data: sdk-test-data@${TEST_DATA_BRANCH_NAME}" - echo "SDK Branch: android-sdk@${SDK_BRANCH_NAME}" + echo "Test Data: sdk-test-data@${TEST_DATA_BRANCH}" + echo "SDK Branch: android-sdk@${SDK_BRANCH}" echo "API Level: ${{ matrix.api-level }}" - name: Check out Java SDK uses: actions/checkout@v4 with: repository: Eppo-exp/android-sdk - ref: ${{ env.SDK_BRANCH_NAME}} + ref: ${{ env.SDK_BRANCH}} - name: Set up JDK 17 uses: actions/setup-java@v3 @@ -66,7 +66,7 @@ jobs: echo "GRADLE_USER_HOME=${HOME}/.gradle" >> $GITHUB_ENV - name: Set up test data - run: make test-data branchName=${{env.TEST_DATA_BRANCH_NAME}} + run: make test-data branchName=${{env.TEST_DATA_BRANCH}} - name: Wait for mock UFC DNS to resolve run: | @@ -131,7 +131,7 @@ jobs: touch app/emulator.log # create log file chmod 777 app/emulator.log # allow writing to log file adb logcat | grep EppoSDK >> app/emulator.log & # pipe all logcat messages into log file as a background process - ./gradlew connectedCheck --no-daemon # run tests + ./gradlew connectedCheck --no-daemon -Pandroid.testInstrumentationRunnerArguments.TEST_DATA_BRANCH=${{ env.TEST_DATA_BRANCH }} # run tests - name: Upload Emulator Logs if: always() diff --git a/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java b/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java index 146ad12..1d9ffdc 100644 --- a/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java +++ b/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java @@ -22,6 +22,7 @@ import android.util.Log; import androidx.annotation.Nullable; import androidx.test.core.app.ApplicationProvider; +import androidx.test.platform.app.InstrumentationRegistry; import cloud.eppo.BaseEppoClient; import cloud.eppo.EppoHttpClient; import cloud.eppo.android.cache.LRUAssignmentCache; @@ -68,8 +69,15 @@ public class EppoClientTest { private static final String TAG = logTag(EppoClient.class); private static final String DUMMY_API_KEY = "mock-api-key"; private static final String DUMMY_OTHER_API_KEY = "another-mock-api-key"; - private static final String TEST_HOST = + + // Use branch if specified by env variable `TEST_DATA_BRANCH`. + private static final String TEST_BRANCH = + InstrumentationRegistry.getArguments().getString("TEST_DATA_BRANCH"); + private static final String TEST_HOST_BASE = "https://us-central1-eppo-qa.cloudfunctions.net/serveGitHubRacTestFile"; + private static final String TEST_HOST = + TEST_HOST_BASE + (TEST_BRANCH != null ? "/b/" + TEST_BRANCH : ""); + private static final String INVALID_HOST = "https://thisisabaddomainforthistest.com"; private final ObjectMapper mapper = new ObjectMapper().registerModule(module()); @Mock AssignmentLogger mockAssignmentLogger; @@ -781,7 +789,7 @@ private void waitForPopulatedCache() { while (!cachePopulated) { if (System.currentTimeMillis() > waitEnd) { throw new InterruptedException( - "Cache file never populated; assuming configuration error"); + "Cache file never populated or smaller than expected 8000 bytes; assuming configuration error"); } long expectedMinimumSizeInBytes = 8000; // Last time this test was updated, cache size was 11,506 bytes From 0e3ad7696206480cfa5c831e27520193b91b1ac2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 09:13:18 -0800 Subject: [PATCH 4/8] chore(deps): bump com.android.application from 8.7.2 to 8.7.3 (#140) Bumps com.android.application from 8.7.2 to 8.7.3. --- updated-dependencies: - dependency-name: com.android.application dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 557a9e6..a95ce1e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.7.2' apply false + id 'com.android.application' version '8.7.3' apply false id 'com.android.library' version '8.7.2' apply false } From d42f41cd8c291e81814c6ba34358733932c7ec11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 09:26:01 -0800 Subject: [PATCH 5/8] chore(deps): bump com.android.library from 8.7.2 to 8.7.3 (#141) Bumps com.android.library from 8.7.2 to 8.7.3. --- updated-dependencies: - dependency-name: com.android.library dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a95ce1e..1323192 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id 'com.android.application' version '8.7.3' apply false - id 'com.android.library' version '8.7.2' apply false + id 'com.android.library' version '8.7.3' apply false } task clean(type: Delete) { From 9370664cca0858c91289269e8959b3790dc7c42d Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Mon, 9 Dec 2024 10:18:31 -0800 Subject: [PATCH 6/8] fix: Version typo (#142) --- eppo/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eppo/build.gradle b/eppo/build.gradle index b55d217..4f7e8b7 100644 --- a/eppo/build.gradle +++ b/eppo/build.gradle @@ -7,7 +7,7 @@ plugins { } group = "cloud.eppo" -version = "4.3.4-SNAPSNOT" +version = "4.3.4-SNAPSHOT" android { buildFeatures.buildConfig true From e46e838a5d6ed1d7255a88f36a7dc8e270f5df9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:25:13 +0000 Subject: [PATCH 7/8] chore(deps): bump com.fasterxml.jackson.core:jackson-databind (#139) Bumps [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) from 2.18.0 to 2.18.2. - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- eppo/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eppo/build.gradle b/eppo/build.gradle index 4f7e8b7..3b647c2 100644 --- a/eppo/build.gradle +++ b/eppo/build.gradle @@ -75,7 +75,7 @@ dependencies { implementation "androidx.core:core:${versions.androidx_core}" implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" implementation "com.github.zafarkhaja:java-semver:${versions.semver}" - implementation "com.fasterxml.jackson.core:jackson-databind:2.18.0" + implementation "com.fasterxml.jackson.core:jackson-databind:2.18.2" testImplementation "junit:junit:${versions.junit}" testImplementation "commons-io:commons-io:${versions.commonsio}" From ffd6204dc08e6e58df6c6f32fbafb48803932d0f Mon Sep 17 00:00:00 2001 From: Tyler Potter Date: Fri, 20 Dec 2024 09:18:30 -0700 Subject: [PATCH 8/8] fix: allow offline init with unobfuscated config (#143) * fix: allow offline init with unobfuscated config * bump version --- eppo/build.gradle | 2 +- .../cloud/eppo/android/EppoClientTest.java | 40 +++++++++++++++++++ .../java/cloud/eppo/android/EppoClient.java | 4 +- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/eppo/build.gradle b/eppo/build.gradle index 3b647c2..4210055 100644 --- a/eppo/build.gradle +++ b/eppo/build.gradle @@ -7,7 +7,7 @@ plugins { } group = "cloud.eppo" -version = "4.3.4-SNAPSHOT" +version = "4.3.5" android { buildFeatures.buildConfig true diff --git a/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java b/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java index 1d9ffdc..4d761c0 100644 --- a/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java +++ b/eppo/src/androidTest/java/cloud/eppo/android/EppoClientTest.java @@ -369,6 +369,46 @@ private void runTestCases() { } } + @Test + public void testOfflineInit() throws IOException { + testOfflineInitFromFile("flags-v1.json"); + } + + @Test + public void testObfuscatedOfflineInit() throws IOException { + testOfflineInitFromFile("flags-v1-obfuscated.json"); + } + + public void testOfflineInitFromFile(String filepath) throws IOException { + AssetManager assets = ApplicationProvider.getApplicationContext().getAssets(); + + InputStream stream = assets.open(filepath); + int size = stream.available(); + byte[] buffer = new byte[size]; + int numBytes = stream.read(buffer); + stream.close(); + + CompletableFuture futureClient = + new EppoClient.Builder("DUMMYKEY", ApplicationProvider.getApplicationContext()) + .isGracefulMode(false) + .offlineMode(true) + .assignmentLogger(mockAssignmentLogger) + .forceReinitialize(true) + .initialConfiguration(buffer) + .buildAndInitAsync() + .thenAccept(client -> Log.i(TAG, "Test client async buildAndInit completed.")); + + Double result = + futureClient + .thenApply( + clVoid -> { + return EppoClient.getInstance().getDoubleAssignment("numeric_flag", "bob", 99.0); + }) + .join(); + + assertEquals(3.14, result, 0.1); + } + @Test public void testCachedConfigurations() { // First initialize successfully diff --git a/eppo/src/main/java/cloud/eppo/android/EppoClient.java b/eppo/src/main/java/cloud/eppo/android/EppoClient.java index d45b81f..f98e05a 100644 --- a/eppo/src/main/java/cloud/eppo/android/EppoClient.java +++ b/eppo/src/main/java/cloud/eppo/android/EppoClient.java @@ -175,13 +175,13 @@ public Builder assignmentCache(IAssignmentCache assignmentCache) { public Builder initialConfiguration(byte[] initialFlagConfigResponse) { this.initialConfiguration = CompletableFuture.completedFuture( - Configuration.builder(initialFlagConfigResponse, true).build()); + new Configuration.Builder(initialFlagConfigResponse).build()); return this; } public Builder initialConfiguration(CompletableFuture initialFlagConfigResponse) { this.initialConfiguration = - initialFlagConfigResponse.thenApply(ic -> Configuration.builder(ic, true).build()); + initialFlagConfigResponse.thenApply(ic -> new Configuration.Builder(ic).build()); return this; }