From de9a928f93679295ad9244b7dc6def1af1d9f7fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:09:30 -0400 Subject: [PATCH 001/134] chore(deps): update dependency dev.openfeature.contrib.providers:flagd to v0.5.8 (#360) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7dee3aae..59d6081a 100644 --- a/pom.xml +++ b/pom.xml @@ -142,7 +142,7 @@ dev.openfeature.contrib.providers flagd - 0.5.7 + 0.5.8 test From 3ae2a541a1c8a9fc568a97aa02301df1353e092b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 11:00:23 +0000 Subject: [PATCH 002/134] chore(deps): update github/codeql-action digest to fff3a80 (#365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index e41418bd..837448aa 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@f9c159f4fded57bd3c8000e5de554cb90fa0b265 + uses: github/codeql-action/init@fff3a80b5bbdd29f1453bf4554afabb83609be14 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f9c159f4fded57bd3c8000e5de554cb90fa0b265 + uses: github/codeql-action/analyze@fff3a80b5bbdd29f1453bf4554afabb83609be14 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 4457de72..f871fbff 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f9c159f4fded57bd3c8000e5de554cb90fa0b265 + uses: github/codeql-action/init@fff3a80b5bbdd29f1453bf4554afabb83609be14 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@f9c159f4fded57bd3c8000e5de554cb90fa0b265 + uses: github/codeql-action/autobuild@fff3a80b5bbdd29f1453bf4554afabb83609be14 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f9c159f4fded57bd3c8000e5de554cb90fa0b265 + uses: github/codeql-action/analyze@fff3a80b5bbdd29f1453bf4554afabb83609be14 From 6d7c43d120d025d180a446ba7769109b94e1be3c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:59:31 +0000 Subject: [PATCH 003/134] chore(deps): update google-github-actions/release-please-action digest to ee9822e (#366) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 346b75b6..afdeec02 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@9997fc940dddf620986d5e88532ffb2cc6e22c1c + - uses: google-github-actions/release-please-action@ee9822ec2c397e8a364d634464339ac43a06e042 id: release with: command: manifest From bac2af3033245db5bb5da18790f86e657a773686 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Mar 2023 01:41:45 +0000 Subject: [PATCH 004/134] chore(deps): update github/codeql-action digest to dc81ae3 (#367) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 837448aa..64db6a25 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@fff3a80b5bbdd29f1453bf4554afabb83609be14 + uses: github/codeql-action/init@dc81ae336830862c46eda3f3aefe6fb65cc21f48 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fff3a80b5bbdd29f1453bf4554afabb83609be14 + uses: github/codeql-action/analyze@dc81ae336830862c46eda3f3aefe6fb65cc21f48 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index f871fbff..16504f1b 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fff3a80b5bbdd29f1453bf4554afabb83609be14 + uses: github/codeql-action/init@dc81ae336830862c46eda3f3aefe6fb65cc21f48 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@fff3a80b5bbdd29f1453bf4554afabb83609be14 + uses: github/codeql-action/autobuild@dc81ae336830862c46eda3f3aefe6fb65cc21f48 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fff3a80b5bbdd29f1453bf4554afabb83609be14 + uses: github/codeql-action/analyze@dc81ae336830862c46eda3f3aefe6fb65cc21f48 From 5e648f6332f08c72a5e232bd6ae2171e6476a05e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 02:17:33 +0000 Subject: [PATCH 005/134] chore(deps): update github/codeql-action digest to bb28e7e (#368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 64db6a25..db68d4ab 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@dc81ae336830862c46eda3f3aefe6fb65cc21f48 + uses: github/codeql-action/init@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dc81ae336830862c46eda3f3aefe6fb65cc21f48 + uses: github/codeql-action/analyze@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 16504f1b..750b7eff 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@dc81ae336830862c46eda3f3aefe6fb65cc21f48 + uses: github/codeql-action/init@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@dc81ae336830862c46eda3f3aefe6fb65cc21f48 + uses: github/codeql-action/autobuild@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dc81ae336830862c46eda3f3aefe6fb65cc21f48 + uses: github/codeql-action/analyze@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f From d7b3ca0513f80e933d25d6ada2ef3cbbbf961b38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 03:08:44 +0000 Subject: [PATCH 006/134] chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.6 (#370) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 59d6081a..7b2810ad 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.5 + 2.7.6 library 1.3 From 0ce5b43a81d5334460e8724f55798486bc9813d0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 20:01:41 +0000 Subject: [PATCH 007/134] chore(deps): update actions/setup-java digest to e42168c (#371) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 6d4127fc..5b5ec34b 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 + uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index db68d4ab..dc079fb8 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 + uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index afdeec02..136265f9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 + uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 with: java-version: '8' distribution: 'temurin' From dfa08b90e1cf3f698f9058f95e7e41567a1934bb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:53:59 -0400 Subject: [PATCH 008/134] chore(deps): update codecov/codecov-action digest to 91e1847 (#372) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 5b5ec34b..35ea03e8 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@cc7fb3f71c712c470a895ac29f8a1fd0fcb52c8a + uses: codecov/codecov-action@91e184765dad936fb6df80d5af0decb809a33dac with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index dc079fb8..e7d6688d 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@cc7fb3f71c712c470a895ac29f8a1fd0fcb52c8a + uses: codecov/codecov-action@91e184765dad936fb6df80d5af0decb809a33dac with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 6a8c911287d8b3d2e35f6455af3496a532a71553 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 05:32:55 +0000 Subject: [PATCH 009/134] chore(deps): update github/codeql-action digest to f0a422f (#373) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index e7d6688d..254e20e9 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f + uses: github/codeql-action/init@f0a422fa27c6cba8d04c33536a1213579b349b14 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f + uses: github/codeql-action/analyze@f0a422fa27c6cba8d04c33536a1213579b349b14 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 750b7eff..4f3d1715 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f + uses: github/codeql-action/init@f0a422fa27c6cba8d04c33536a1213579b349b14 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f + uses: github/codeql-action/autobuild@f0a422fa27c6cba8d04c33536a1213579b349b14 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@bb28e7e59e2ad6c1e5400e671795b2fa1b2fca6f + uses: github/codeql-action/analyze@f0a422fa27c6cba8d04c33536a1213579b349b14 From bdb08d7af809bfb4593cf38830b843fb433a95ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:30:10 +0000 Subject: [PATCH 010/134] chore(deps): update actions/setup-java digest to 191ba8c (#375) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 35ea03e8..ca1ad016 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 + uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 254e20e9..5b3b2b40 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 + uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 136265f9..0d912ce4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@e42168ca1a833395367a6bce0db2a62f7fe4da81 + uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d with: java-version: '8' distribution: 'temurin' From 23c4c4cef9ff0d18aec44af5c0c808439124d142 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 07:54:38 +0000 Subject: [PATCH 011/134] chore(deps): update github/codeql-action digest to fa7cce4 (#376) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 5b3b2b40..ac986219 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@f0a422fa27c6cba8d04c33536a1213579b349b14 + uses: github/codeql-action/init@fa7cce4d4be476d3edb355e94da56ebe046b0370 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f0a422fa27c6cba8d04c33536a1213579b349b14 + uses: github/codeql-action/analyze@fa7cce4d4be476d3edb355e94da56ebe046b0370 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 4f3d1715..59377740 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f0a422fa27c6cba8d04c33536a1213579b349b14 + uses: github/codeql-action/init@fa7cce4d4be476d3edb355e94da56ebe046b0370 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@f0a422fa27c6cba8d04c33536a1213579b349b14 + uses: github/codeql-action/autobuild@fa7cce4d4be476d3edb355e94da56ebe046b0370 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f0a422fa27c6cba8d04c33536a1213579b349b14 + uses: github/codeql-action/analyze@fa7cce4d4be476d3edb355e94da56ebe046b0370 From 5c335d45393227cdeb3813630ee6ef9d4196916d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 15:59:03 +0000 Subject: [PATCH 012/134] chore(deps): update github/codeql-action digest to 66aeadb (#377) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index ac986219..aeddda3f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@fa7cce4d4be476d3edb355e94da56ebe046b0370 + uses: github/codeql-action/init@66aeadb4c995463a91b7d055358e3325c44e3921 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fa7cce4d4be476d3edb355e94da56ebe046b0370 + uses: github/codeql-action/analyze@66aeadb4c995463a91b7d055358e3325c44e3921 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 59377740..58dd0370 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fa7cce4d4be476d3edb355e94da56ebe046b0370 + uses: github/codeql-action/init@66aeadb4c995463a91b7d055358e3325c44e3921 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@fa7cce4d4be476d3edb355e94da56ebe046b0370 + uses: github/codeql-action/autobuild@66aeadb4c995463a91b7d055358e3325c44e3921 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fa7cce4d4be476d3edb355e94da56ebe046b0370 + uses: github/codeql-action/analyze@66aeadb4c995463a91b7d055358e3325c44e3921 From ae307892a5fbc9ac02db47e42acc1a723b714938 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 00:56:58 +0000 Subject: [PATCH 013/134] chore(deps): update github/codeql-action digest to f32426b (#378) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index aeddda3f..4e623f32 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@66aeadb4c995463a91b7d055358e3325c44e3921 + uses: github/codeql-action/init@f32426ba96560beecf71186b24134fb3f613f377 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@66aeadb4c995463a91b7d055358e3325c44e3921 + uses: github/codeql-action/analyze@f32426ba96560beecf71186b24134fb3f613f377 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 58dd0370..43215ba5 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@66aeadb4c995463a91b7d055358e3325c44e3921 + uses: github/codeql-action/init@f32426ba96560beecf71186b24134fb3f613f377 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@66aeadb4c995463a91b7d055358e3325c44e3921 + uses: github/codeql-action/autobuild@f32426ba96560beecf71186b24134fb3f613f377 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@66aeadb4c995463a91b7d055358e3325c44e3921 + uses: github/codeql-action/analyze@f32426ba96560beecf71186b24134fb3f613f377 From 9b778277968851752bd569a09f6609f2cb3ffe48 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 22:40:35 +0000 Subject: [PATCH 014/134] chore(deps): update github/codeql-action digest to 988e1bc (#379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4e623f32..bb21dca4 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@f32426ba96560beecf71186b24134fb3f613f377 + uses: github/codeql-action/init@988e1bc94181d8b9c03964b72e28974e2dbca322 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f32426ba96560beecf71186b24134fb3f613f377 + uses: github/codeql-action/analyze@988e1bc94181d8b9c03964b72e28974e2dbca322 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 43215ba5..295ab997 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f32426ba96560beecf71186b24134fb3f613f377 + uses: github/codeql-action/init@988e1bc94181d8b9c03964b72e28974e2dbca322 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@f32426ba96560beecf71186b24134fb3f613f377 + uses: github/codeql-action/autobuild@988e1bc94181d8b9c03964b72e28974e2dbca322 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f32426ba96560beecf71186b24134fb3f613f377 + uses: github/codeql-action/analyze@988e1bc94181d8b9c03964b72e28974e2dbca322 From ec3111f5d7fb12343a45ff70296238cf747554ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 07:06:21 +0000 Subject: [PATCH 015/134] chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.7.3.4 (#380) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7b2810ad..ec454fc0 100644 --- a/pom.xml +++ b/pom.xml @@ -431,7 +431,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.3.3 + 4.7.3.4 spotbugs-exclusions.xml From 037d61128e1e8a06a16d5ac899c2c92762baa4b3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 03:01:43 +0000 Subject: [PATCH 016/134] chore(deps): update github/codeql-action digest to 98f7bbd (#383) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index bb21dca4..d0b28fa2 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@988e1bc94181d8b9c03964b72e28974e2dbca322 + uses: github/codeql-action/init@98f7bbd6102f2c11acb5631e38386a1837dca5a5 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@988e1bc94181d8b9c03964b72e28974e2dbca322 + uses: github/codeql-action/analyze@98f7bbd6102f2c11acb5631e38386a1837dca5a5 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 295ab997..386ef2d4 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@988e1bc94181d8b9c03964b72e28974e2dbca322 + uses: github/codeql-action/init@98f7bbd6102f2c11acb5631e38386a1837dca5a5 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@988e1bc94181d8b9c03964b72e28974e2dbca322 + uses: github/codeql-action/autobuild@98f7bbd6102f2c11acb5631e38386a1837dca5a5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@988e1bc94181d8b9c03964b72e28974e2dbca322 + uses: github/codeql-action/analyze@98f7bbd6102f2c11acb5631e38386a1837dca5a5 From a737c3a36bb5899c7e4b1efab69a3d4f13f24325 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 08:22:19 +0000 Subject: [PATCH 017/134] chore(deps): update actions/setup-java digest to ddb82ce (#381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index ca1ad016..ea163f57 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d + uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d0b28fa2..e4e9be4a 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 - uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d + uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d912ce4..98eb40b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@191ba8c6ba49737c558c820f47161f35b262c87d + uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: java-version: '8' distribution: 'temurin' From 22828d1d3f59371205d36b8419dd61647046043f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 13:59:29 +0000 Subject: [PATCH 018/134] chore(deps): update google-github-actions/release-please-action digest to f7edb9e (#384) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98eb40b8..d991d081 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@ee9822ec2c397e8a364d634464339ac43a06e042 + - uses: google-github-actions/release-please-action@f7edb9e61420a022c0f1123edaf342d7e127df92 id: release with: command: manifest From f51d0201c62b558a89a1e3ab77e666ce98ecba0b Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 11 Apr 2023 15:27:57 -0400 Subject: [PATCH 019/134] chore: update readme using template (#382) * chore: update readme using template Signed-off-by: Todd Baert * fixup: add complete API documentation Signed-off-by: Todd Baert * Update README.md Co-authored-by: Justin Abrahms Signed-off-by: Todd Baert * Update README.md Co-authored-by: Justin Abrahms Signed-off-by: Todd Baert --------- Signed-off-by: Todd Baert Co-authored-by: Justin Abrahms --- CONTRIBUTING.md | 20 ++++- README.md | 225 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 169 insertions(+), 76 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 84c8d017..f18fa1af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -Welcome! Super happy to have you here. +## Welcome! Super happy to have you here. A few things. @@ -10,10 +10,26 @@ We're not keen on vendor-specific stuff in this library, but if there are change Any contributions you make are expected to be tested with unit tests. You can validate these work with `gradle test`, or the automation itself will run them for you when you make a PR. -Your code is supposed to work with Java 11+. +Your code is supposed to work with Java 8+. If you think we might be out of date with the spec, you can check that by invoking `python spec_finder.py` in the root of the repository. This will validate we have tests defined for all of the specification entries we know about. If you're adding tests to cover something in the spec, use the `@Specification` annotation like you see throughout the test suites. +## Integration tests + +The continuous integration runs a set of [gherkin integration tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with + +``` +docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest +``` +and then run +``` +mvn test -P integration-test +``` + +## Releasing + +See [releasing](./docs/release.md). + Thanks and looking forward to your issues and pull requests. diff --git a/README.md b/README.md index 1b135dfb..aef00380 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,43 @@ -# OpenFeature SDK for Java + +

+ + + + OpenFeature Logo + +

+

OpenFeature Java SDK

+ +[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.5.2&color=yellow)](https://github.com/open-feature/spec/tree/v0.5.2) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk) [![javadoc](https://javadoc.io/badge2/dev.openfeature/sdk/javadoc.svg)](https://javadoc.io/doc/dev.openfeature/sdk) [![Project Status: Active โ€“ The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) -[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.5.2&color=yellow)](https://github.com/open-feature/spec/tree/v0.5.2) [![Known Vulnerabilities](https://snyk.io/test/github/open-feature/java-sdk/badge.svg)](https://snyk.io/test/github/open-feature/java-sdk) [![on-merge](https://github.com/open-feature/java-sdk/actions/workflows/merge.yml/badge.svg)](https://github.com/open-feature/java-sdk/actions/workflows/merge.yml) [![codecov](https://codecov.io/gh/open-feature/java-sdk/branch/main/graph/badge.svg?token=XMS9L7PBY1)](https://codecov.io/gh/open-feature/java-sdk) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6241/badge)](https://bestpractices.coreinfrastructure.org/projects/6241) -This is the Java implementation of [OpenFeature](https://openfeature.dev), a vendor-agnostic abstraction library for evaluating feature flags. - -We support multiple data types for flags (numbers, strings, booleans, objects) as well as hooks, which can alter the lifecycle of a flag evaluation. +## ๐Ÿ‘‹ Hey there! Thanks for checking out the OpenFeature Java SDK -This library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices. - -## Usage - -While `Boolean` provides the simplest introduction, we offer a variety of flag types. - -```java -import dev.openfeature.sdk.Structure; - -class MyClass { - public UI booleanExample() { - // Should we render the redesign? Or the default webpage? - if (client.getBooleanValue("redesign_enabled", false)) { - return render_redesign(); - } - return render_normal(); - } +### What is OpenFeature? - public Template stringExample() { - // Get the template to load for the custom new homepage - String template = client.getStringValue("homepage_template", "default-homepage.html"); - return render_template(template); - } +[OpenFeature][openfeature-website] is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. - public List numberExample() { - // How many modules should we be fetching? - Integer count = client.getIntegerValue("module-fetch-count", 4); - return fetch_modules(count); - } +### Why standardize feature flags? - public HomepageModule structureExample() { - Structure obj = client.getObjectValue("hero-module", previouslyDefinedDefaultStructure); - return HomepageModule.builder() - .title(obj.getValue("title")) - .body(obj.getValue("description")) - .build(); - } -} -``` +Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition. -For complete documentation, visit: https://docs.openfeature.dev/docs/category/concepts +## ๐Ÿ” Requirements: -## Requirements - Java 8+ (compiler target is 1.8) -## Installation +Note that this library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices. -### Add it to your build +## ๐Ÿ“ฆ Installation: + +### Maven -#### Maven ```xml @@ -88,7 +63,7 @@ If you would like snapshot builds, this is the relevant repository information: ``` -#### Gradle +### Gradle ```groovy dependencies { @@ -97,51 +72,153 @@ dependencies { ``` -### Configure it -To configure it, you'll need to add a provider to the global singleton `OpenFeatureAPI`. From there, you can generate a `Client` which is usable by your code. While you'll likely want a provider for your specific backend, we've provided a `NoOpProvider`, which simply returns the default passed in. +### Software Bill of Materials (SBOM) + +We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts. + +## ๐ŸŒŸ Features: + +- support for various backend [providers](https://docs.openfeature.dev/docs/reference/concepts/provider) +- easy integration and extension via [hooks](https://docs.openfeature.dev/docs/reference/concepts/hooks) +- bool, string, numeric and object flag types +- [context-aware](https://docs.openfeature.dev/docs/reference/concepts/evaluation-context) evaluation + +## ๐Ÿš€ Usage: + +### Basics: + ```java -class MyApp { - public void example(){ - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new NoOpProvider()); - Client client = api.getClient(); - // Now use your `client` instance to evaluate some feature flags! - } +public void example(){ + + // configure a provider + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + api.setProvider(new MyProviderOfChoice()); + + // create a client + Client client = api.getClient(); + + // get a bool flag value + boolean flagValue = client.getBooleanValue("boolFlag", false); } ``` -## Contacting us -We hold regular meetings which you can see [here](https://github.com/open-feature/community/#meetings-and-events). -We are also present on the `#openfeature` channel in the [CNCF slack](https://slack.cncf.io/). +### Context-aware evaluation: -## Developing +Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. +In OpenFeature, we refer to this as [`targeting`](https://docs.openfeature.dev/specification/glossary#targeting). +If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. -### Integration tests +```java +// global context for static data +OpenFeatureAPI api = OpenFeatureAPI.getInstance(); +Map attributes = new HashMap<>(); +attributes.put("appVersion", new Value(System.getEnv("APP_VERSION"))); +EvaluationContext apiCtx = new ImmutableContext(attributes); +api.setEvaluationContext(apiCtx); + +// request context +Map attributes = new HashMap<>(); +attributes.put("email", new Value(session.getAttribute("email"))); +attributes.put("product", new Value(productId)); +String targetingKey = session.getId(); +EvaluationContext reqCtx = new ImmutableContext(targetingKey, attributes); + +// use merged contextual data to determine a flag value +boolean flagValue = client.getBooleanValue("some-flag", false, reqCtx); +``` -The continuous integration runs a set of [gherkin integration tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with +### Providers: +To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/java-sdk-contrib) available under the OpenFeature organization. Finally, youโ€™ll then need to write the provider itself. This can be accomplished by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. + +```java +public class MyProvider implements FeatureProvider { +@Override + public Metadata getMetadata() { + return () -> "My Provider"; + } + + @Override + public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { + // resolve a boolean flag value + } + + @Override + public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) { + // resolve a string flag value + } + + @Override + public ProviderEvaluation getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) { + // resolve an int flag value + } + + @Override + public ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) { + // resolve a double flag value + } + + @Override + public ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) { + // resolve an object flag value + } +} ``` -docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest -``` -and then run -``` -mvn test -P integration-test + +See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available providers. + +### Hooks: + +Hooks are a mechanism that allow for the addition of arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validation of the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. + +```java +public class MyHook implements Hook { + /** + * + * @param ctx Information about the particular flag evaluation + * @param details Information about how the flag was resolved, including any resolved values. + * @param hints An immutable mapping of data for users to communicate to the hooks. + */ + @Override + public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) { + System.out.println("After evaluation!"); + } +} ``` -## Releasing +See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available hooks. -See [releasing](./docs/release.md). +### Logging: -### Software Bill of Materials (SBOM) +The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation. -We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts. +### Complete API documentation: -## Contributors +See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for the complete API documentation. -Thanks so much to our contributors. +## โญ๏ธ Support the project + +- Give this repo a โญ๏ธ! +- Follow us social media: + - Twitter: [@openfeature](https://twitter.com/openfeature) + - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) +- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) +- For more check out our [community page](https://docs.openfeature.dev/community/) + +## ๐Ÿค Contributing + +Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide. + +### Thanks to everyone that has already contributed - Pictures of the folks who have contributed to the project + Pictures of the folks who have contributed to the project Made with [contrib.rocks](https://contrib.rocks). + +## ๐Ÿ“œ License + +[Apache License 2.0](LICENSE) + +[openfeature-website]: https://openfeature.dev From ade4878abc1efd993f2dc2977adbc0cc45b84be2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 13:40:31 -0700 Subject: [PATCH 020/134] chore(deps): update dependency org.jacoco:jacoco-maven-plugin to v0.8.9 (#374) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Kavindu Dodanduwa --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ec454fc0..5c1cc240 100644 --- a/pom.xml +++ b/pom.xml @@ -279,7 +279,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.9 From 507255316614cef8653c833d7c83322f999485ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 02:15:10 +0000 Subject: [PATCH 021/134] chore(deps): update codecov/codecov-action digest to 40a12dc (#385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index ea163f57..2be08dfd 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@91e184765dad936fb6df80d5af0decb809a33dac + uses: codecov/codecov-action@40a12dcee2df644d47232dde008099a3e9e4f865 with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index e4e9be4a..1774b2ec 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@91e184765dad936fb6df80d5af0decb809a33dac + uses: codecov/codecov-action@40a12dcee2df644d47232dde008099a3e9e4f865 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From f1ecfac6aaac1102bd380a25935a42c64eda441b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 08:26:45 +0000 Subject: [PATCH 022/134] chore(deps): update github/codeql-action digest to ed6c499 (#386) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 1774b2ec..4e320cb6 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@98f7bbd6102f2c11acb5631e38386a1837dca5a5 + uses: github/codeql-action/init@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@98f7bbd6102f2c11acb5631e38386a1837dca5a5 + uses: github/codeql-action/analyze@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 386ef2d4..7f592841 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@98f7bbd6102f2c11acb5631e38386a1837dca5a5 + uses: github/codeql-action/init@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@98f7bbd6102f2c11acb5631e38386a1837dca5a5 + uses: github/codeql-action/autobuild@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@98f7bbd6102f2c11acb5631e38386a1837dca5a5 + uses: github/codeql-action/analyze@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 From 702957c517345906db80c0805e02e22ee18fa70c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 15:57:00 +0000 Subject: [PATCH 023/134] chore(deps): update google-github-actions/release-please-action digest to c078ea3 (#387) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d991d081..6a561915 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@f7edb9e61420a022c0f1123edaf342d7e127df92 + - uses: google-github-actions/release-please-action@c078ea33917ab8cfa5300e48f4b7e6b16606aede id: release with: command: manifest From f3e65db54e24926f529e939b5a27f605c46f3185 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 21:07:50 +0000 Subject: [PATCH 024/134] chore(deps): update actions/checkout digest to 83b7061 (#389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-code-scanning.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 2be08dfd..48b48abe 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4e320cb6..b8e09af5 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the code - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6a561915..162aab9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: # These steps are only run if this was a merged release-please PR - name: checkout if: ${{ steps.release.outputs.releases_created }} - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 7f592841..83b0899c 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From 519c32a087e94376b9a245ad9c1a4fab360adfe2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 16:21:16 +0000 Subject: [PATCH 025/134] chore(deps): update github/codeql-action digest to d944b34 (#390) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index b8e09af5..2b1c82e4 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 + uses: github/codeql-action/init@d944b3423d194ae3a11d1d7291ab2f38eb94207a with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 + uses: github/codeql-action/analyze@d944b3423d194ae3a11d1d7291ab2f38eb94207a diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 83b0899c..bb47da0e 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 + uses: github/codeql-action/init@d944b3423d194ae3a11d1d7291ab2f38eb94207a with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 + uses: github/codeql-action/autobuild@d944b3423d194ae3a11d1d7291ab2f38eb94207a - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ed6c4995fcfc90fa1e870bf955dd15e010cf71e8 + uses: github/codeql-action/analyze@d944b3423d194ae3a11d1d7291ab2f38eb94207a From 9c98e83ed6a1a471b6c5488b8c87681fd92dd77d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 10:38:27 -0700 Subject: [PATCH 026/134] chore(deps): update actions/checkout digest to 8e5e7e5 (#391) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-code-scanning.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 48b48abe..b4c9ce8a 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 2b1c82e4..f013483f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the code - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 162aab9d..b4269a85 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: # These steps are only run if this was a merged release-please PR - name: checkout if: ${{ steps.release.outputs.releases_created }} - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index bb47da0e..12e1cf0f 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@83b7061638ee4956cf7545a6f7efe594e5ad0247 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From 813c7e21ab933680f507dc077ceabbdbda9299e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 22:09:55 +0000 Subject: [PATCH 027/134] chore(deps): update github/codeql-action digest to dc04638 (#392) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index f013483f..30c28407 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@d944b3423d194ae3a11d1d7291ab2f38eb94207a + uses: github/codeql-action/init@dc046388f30eacf938aadd32064285f437bd9c04 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d944b3423d194ae3a11d1d7291ab2f38eb94207a + uses: github/codeql-action/analyze@dc046388f30eacf938aadd32064285f437bd9c04 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 12e1cf0f..06a65ab1 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@d944b3423d194ae3a11d1d7291ab2f38eb94207a + uses: github/codeql-action/init@dc046388f30eacf938aadd32064285f437bd9c04 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@d944b3423d194ae3a11d1d7291ab2f38eb94207a + uses: github/codeql-action/autobuild@dc046388f30eacf938aadd32064285f437bd9c04 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d944b3423d194ae3a11d1d7291ab2f38eb94207a + uses: github/codeql-action/analyze@dc046388f30eacf938aadd32064285f437bd9c04 From 0f76349a505b10aed9cf28b72821f51848d804ad Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Fri, 14 Apr 2023 16:40:26 -0400 Subject: [PATCH 028/134] update doc links --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aef00380..ba880dce 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,10 @@ We publish SBOMs with all of our releases as of 0.3.0. You can find them in Mave ## ๐ŸŒŸ Features: -- support for various backend [providers](https://docs.openfeature.dev/docs/reference/concepts/provider) -- easy integration and extension via [hooks](https://docs.openfeature.dev/docs/reference/concepts/hooks) +- support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider) +- easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks) - bool, string, numeric and object flag types -- [context-aware](https://docs.openfeature.dev/docs/reference/concepts/evaluation-context) evaluation +- [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation ## ๐Ÿš€ Usage: @@ -105,7 +105,7 @@ public void example(){ ### Context-aware evaluation: Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. -In OpenFeature, we refer to this as [`targeting`](https://docs.openfeature.dev/specification/glossary#targeting). +In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting). If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. ```java @@ -165,7 +165,7 @@ public class MyProvider implements FeatureProvider { } ``` -See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available providers. +See [here](https://openfeature.dev/docs/reference/technologies/server/java) for a catalog of available providers. ### Hooks: @@ -186,7 +186,7 @@ public class MyHook implements Hook { } ``` -See [here](https://docs.openfeature.dev/docs/reference/technologies/server/java) for a catalog of available hooks. +See [here](https://openfeature.dev/docs/reference/technologies/server/java) for a catalog of available hooks. ### Logging: @@ -203,7 +203,7 @@ See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for - Twitter: [@openfeature](https://twitter.com/openfeature) - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) - Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) -- For more check out our [community page](https://docs.openfeature.dev/community/) +- For more check out our [community page](https://openfeature.dev/community/) ## ๐Ÿค Contributing From 43a75d080c3594669fe6c594b2818ee9fe22955e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Apr 2023 01:13:12 +0000 Subject: [PATCH 029/134] chore(deps): update actions/checkout digest to 47fbe2d (#393) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-code-scanning.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index b4c9ce8a..b45d73de 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 30c28407..42c31b78 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4269a85..50a5be11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: # These steps are only run if this was a merged release-please PR - name: checkout if: ${{ steps.release.outputs.releases_created }} - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 06a65ab1..825c653d 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From 28e191d4231c6c04971724e3d88166260a96bef4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Apr 2023 05:41:49 +0000 Subject: [PATCH 030/134] chore(deps): update github/codeql-action digest to be2b53b (#394) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 42c31b78..01c115d5 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@dc046388f30eacf938aadd32064285f437bd9c04 + uses: github/codeql-action/init@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dc046388f30eacf938aadd32064285f437bd9c04 + uses: github/codeql-action/analyze@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 825c653d..fd11bc01 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@dc046388f30eacf938aadd32064285f437bd9c04 + uses: github/codeql-action/init@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@dc046388f30eacf938aadd32064285f437bd9c04 + uses: github/codeql-action/autobuild@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dc046388f30eacf938aadd32064285f437bd9c04 + uses: github/codeql-action/analyze@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 From 2ff65b8344d0a3ffe6daebc3fb9b40ade21e2d7e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 00:32:17 +0000 Subject: [PATCH 031/134] chore(deps): update github/codeql-action digest to 9a866ed (#395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 01c115d5..8d818fca 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 + uses: github/codeql-action/init@9a866ed4524fc3422c3af1e446dab8efa3503411 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 + uses: github/codeql-action/analyze@9a866ed4524fc3422c3af1e446dab8efa3503411 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index fd11bc01..78c241ea 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 + uses: github/codeql-action/init@9a866ed4524fc3422c3af1e446dab8efa3503411 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 + uses: github/codeql-action/autobuild@9a866ed4524fc3422c3af1e446dab8efa3503411 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@be2b53b5c797426cecc09bfc3edf5e2cc97ddd56 + uses: github/codeql-action/analyze@9a866ed4524fc3422c3af1e446dab8efa3503411 From a5eaf79cf9d039ab5319d8c4101b0fd8c395166e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 03:01:24 +0000 Subject: [PATCH 032/134] chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.7 (#396) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c1cc240..899cedcc 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.6 + 2.7.7 library 1.3 From b55ed6cf7417f248b44d9ca86535deee7c80cfcc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 01:46:49 +0000 Subject: [PATCH 033/134] chore(deps): update github/codeql-action digest to afdf30f (#397) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 8d818fca..1cddeca0 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@9a866ed4524fc3422c3af1e446dab8efa3503411 + uses: github/codeql-action/init@afdf30f3115691166cc85051ca5e0ee04becc2e9 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9a866ed4524fc3422c3af1e446dab8efa3503411 + uses: github/codeql-action/analyze@afdf30f3115691166cc85051ca5e0ee04becc2e9 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 78c241ea..3bc8b8e7 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9a866ed4524fc3422c3af1e446dab8efa3503411 + uses: github/codeql-action/init@afdf30f3115691166cc85051ca5e0ee04becc2e9 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@9a866ed4524fc3422c3af1e446dab8efa3503411 + uses: github/codeql-action/autobuild@afdf30f3115691166cc85051ca5e0ee04becc2e9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9a866ed4524fc3422c3af1e446dab8efa3503411 + uses: github/codeql-action/analyze@afdf30f3115691166cc85051ca5e0ee04becc2e9 From 30155712bc35a070febc5761b1ad03dc25183a26 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 19:48:49 +0000 Subject: [PATCH 034/134] chore(deps): update actions/checkout digest to f095bcc (#398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-code-scanning.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index b45d73de..b0e7177b 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f + - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa with: diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 1cddeca0..fc9d7ce4 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the code - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f + uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 50a5be11..ccf8d7cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: # These steps are only run if this was a merged release-please PR - name: checkout if: ${{ steps.release.outputs.releases_created }} - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f + uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 3bc8b8e7..55011b16 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f + uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From 427d5a627251061651040e841d5e4db582f03cd4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:29:31 +0000 Subject: [PATCH 035/134] chore(deps): update codecov/codecov-action digest to 6757614 (#400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index b0e7177b..20f96cda 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@40a12dcee2df644d47232dde008099a3e9e4f865 + uses: codecov/codecov-action@6757614f24a05cb3f8641137b1ed46ed44d19fbc with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index fc9d7ce4..be6898fa 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@40a12dcee2df644d47232dde008099a3e9e4f865 + uses: codecov/codecov-action@6757614f24a05cb3f8641137b1ed46ed44d19fbc with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From c92cd2ccfeb028a43637a545e56142305f76c833 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 21:27:29 +0000 Subject: [PATCH 036/134] chore(deps): update github/codeql-action digest to a8affb0 (#401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index be6898fa..16eeb44f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@afdf30f3115691166cc85051ca5e0ee04becc2e9 + uses: github/codeql-action/init@a8affb06395df1b3b725247becf69d1bf4459333 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@afdf30f3115691166cc85051ca5e0ee04becc2e9 + uses: github/codeql-action/analyze@a8affb06395df1b3b725247becf69d1bf4459333 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 55011b16..d9461e50 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@afdf30f3115691166cc85051ca5e0ee04becc2e9 + uses: github/codeql-action/init@a8affb06395df1b3b725247becf69d1bf4459333 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@afdf30f3115691166cc85051ca5e0ee04becc2e9 + uses: github/codeql-action/autobuild@a8affb06395df1b3b725247becf69d1bf4459333 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@afdf30f3115691166cc85051ca5e0ee04becc2e9 + uses: github/codeql-action/analyze@a8affb06395df1b3b725247becf69d1bf4459333 From 212590e5e26317a4e70caca4d201e21cb7ffa7b4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 02:33:20 +0000 Subject: [PATCH 037/134] chore(deps): update codecov/codecov-action digest to 894ff02 (#402) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 20f96cda..0f0d83f9 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@6757614f24a05cb3f8641137b1ed46ed44d19fbc + uses: codecov/codecov-action@894ff025c7b54547a9a2a1e9f228beae737ad3c2 with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 16eeb44f..326c7305 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@6757614f24a05cb3f8641137b1ed46ed44d19fbc + uses: codecov/codecov-action@894ff025c7b54547a9a2a1e9f228beae737ad3c2 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 311b73fe353ea723f2aa8df70b7ec92e91b8d0f8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 07:26:38 +0000 Subject: [PATCH 038/134] chore(deps): update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.2.2 (#403) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 899cedcc..177a38d0 100644 --- a/pom.xml +++ b/pom.xml @@ -464,7 +464,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.2.1 + 3.2.2 checkstyle.xml UTF-8 From 6898514fca1f4c97edd1453217b4b6d70d996803 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Apr 2023 06:02:50 +0000 Subject: [PATCH 039/134] chore(deps): update github/codeql-action digest to c5f3f01 (#404) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 326c7305..3806946e 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@a8affb06395df1b3b725247becf69d1bf4459333 + uses: github/codeql-action/init@c5f3f016aedaa90345726465387734d1941bdb3a with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a8affb06395df1b3b725247becf69d1bf4459333 + uses: github/codeql-action/analyze@c5f3f016aedaa90345726465387734d1941bdb3a diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index d9461e50..84aef0cc 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@a8affb06395df1b3b725247becf69d1bf4459333 + uses: github/codeql-action/init@c5f3f016aedaa90345726465387734d1941bdb3a with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@a8affb06395df1b3b725247becf69d1bf4459333 + uses: github/codeql-action/autobuild@c5f3f016aedaa90345726465387734d1941bdb3a - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a8affb06395df1b3b725247becf69d1bf4459333 + uses: github/codeql-action/analyze@c5f3f016aedaa90345726465387734d1941bdb3a From a5f076b37c0cba94cc7ae22577abdba43ee011ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 06:07:59 +0000 Subject: [PATCH 040/134] chore(deps): update github/codeql-action digest to a9648ea (#405) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 3806946e..adaedc54 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@c5f3f016aedaa90345726465387734d1941bdb3a + uses: github/codeql-action/init@a9648ea7c684e61497d9a56b7b560a9640298dce with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c5f3f016aedaa90345726465387734d1941bdb3a + uses: github/codeql-action/analyze@a9648ea7c684e61497d9a56b7b560a9640298dce diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 84aef0cc..420cf922 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c5f3f016aedaa90345726465387734d1941bdb3a + uses: github/codeql-action/init@a9648ea7c684e61497d9a56b7b560a9640298dce with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@c5f3f016aedaa90345726465387734d1941bdb3a + uses: github/codeql-action/autobuild@a9648ea7c684e61497d9a56b7b560a9640298dce - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c5f3f016aedaa90345726465387734d1941bdb3a + uses: github/codeql-action/analyze@a9648ea7c684e61497d9a56b7b560a9640298dce From cd27e38f676417e37f7a75cc8413b42350c088cc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:59:23 +0000 Subject: [PATCH 041/134] chore(deps): update google-github-actions/release-please-action digest to 8475937 (#406) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ccf8d7cb..d55722b5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@c078ea33917ab8cfa5300e48f4b7e6b16606aede + - uses: google-github-actions/release-please-action@84759371f245a9245d04f684a8207ced70852d7e id: release with: command: manifest From c426e6646f55e6575f0e1c044e4aa2a8efc2e0c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 02:30:09 +0000 Subject: [PATCH 042/134] chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.8 (#408) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 177a38d0..5569ead3 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.7 + 2.7.8 library 1.3 From 5abe971bdba796cfb435ee02e72179ae406a05f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 08:09:03 +0000 Subject: [PATCH 043/134] chore(deps): update github/codeql-action digest to da583b0 (#409) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index adaedc54..e12236d8 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@a9648ea7c684e61497d9a56b7b560a9640298dce + uses: github/codeql-action/init@da583b07a7c587e17604358c799ad8adf110f3e4 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a9648ea7c684e61497d9a56b7b560a9640298dce + uses: github/codeql-action/analyze@da583b07a7c587e17604358c799ad8adf110f3e4 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 420cf922..8b3f1e38 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@a9648ea7c684e61497d9a56b7b560a9640298dce + uses: github/codeql-action/init@da583b07a7c587e17604358c799ad8adf110f3e4 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@a9648ea7c684e61497d9a56b7b560a9640298dce + uses: github/codeql-action/autobuild@da583b07a7c587e17604358c799ad8adf110f3e4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a9648ea7c684e61497d9a56b7b560a9640298dce + uses: github/codeql-action/analyze@da583b07a7c587e17604358c799ad8adf110f3e4 From 2df3205c747a8f156e38f8510d3f95f49527f6a8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 03:35:33 +0000 Subject: [PATCH 044/134] chore(deps): update github/codeql-action digest to dcf71cf (#411) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index e12236d8..460dd60b 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@da583b07a7c587e17604358c799ad8adf110f3e4 + uses: github/codeql-action/init@dcf71cf79bcf5f35de270a5eaece62a77b559094 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@da583b07a7c587e17604358c799ad8adf110f3e4 + uses: github/codeql-action/analyze@dcf71cf79bcf5f35de270a5eaece62a77b559094 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 8b3f1e38..c838c356 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@da583b07a7c587e17604358c799ad8adf110f3e4 + uses: github/codeql-action/init@dcf71cf79bcf5f35de270a5eaece62a77b559094 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@da583b07a7c587e17604358c799ad8adf110f3e4 + uses: github/codeql-action/autobuild@dcf71cf79bcf5f35de270a5eaece62a77b559094 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@da583b07a7c587e17604358c799ad8adf110f3e4 + uses: github/codeql-action/analyze@dcf71cf79bcf5f35de270a5eaece62a77b559094 From be9d6523ff0cb3d42e68d8f4d36fe9661ec25eca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Apr 2023 03:55:44 +0000 Subject: [PATCH 045/134] chore(deps): update github/codeql-action digest to f31a31c (#412) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 460dd60b..91f6ad24 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@dcf71cf79bcf5f35de270a5eaece62a77b559094 + uses: github/codeql-action/init@f31a31c052207cc13b328d6295c5b728bb49568c with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dcf71cf79bcf5f35de270a5eaece62a77b559094 + uses: github/codeql-action/analyze@f31a31c052207cc13b328d6295c5b728bb49568c diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index c838c356..b5b81b7a 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@dcf71cf79bcf5f35de270a5eaece62a77b559094 + uses: github/codeql-action/init@f31a31c052207cc13b328d6295c5b728bb49568c with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@dcf71cf79bcf5f35de270a5eaece62a77b559094 + uses: github/codeql-action/autobuild@f31a31c052207cc13b328d6295c5b728bb49568c - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@dcf71cf79bcf5f35de270a5eaece62a77b559094 + uses: github/codeql-action/analyze@f31a31c052207cc13b328d6295c5b728bb49568c From 5b10d399cb2fdf38fe46105d53fa2ae36eb2e0b2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:06:33 -0400 Subject: [PATCH 046/134] chore(deps): update dependency org.jacoco:jacoco-maven-plugin to v0.8.10 (#407) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5569ead3..d25b175f 100644 --- a/pom.xml +++ b/pom.xml @@ -279,7 +279,7 @@ org.jacoco jacoco-maven-plugin - 0.8.9 + 0.8.10 From 854d0be0f473c212884163680e2ee5df5eded0c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:13:03 -0400 Subject: [PATCH 047/134] fix(deps): update junit5 monorepo (#410) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index d25b175f..3af99bd7 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ UTF-8 1.8 ${maven.compiler.source} - 5.9.2 + 5.9.3 **/integration/*.java ${groupId}.${artifactId} @@ -109,7 +109,7 @@ org.junit.platform junit-platform-suite - 1.9.2 + 1.9.3 test @@ -161,7 +161,7 @@ org.junit junit-bom - 5.9.2 + 5.9.3 pom import From f0f5d284169081cae8fc88cffa04d17ac776a51f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Apr 2023 23:37:52 +0000 Subject: [PATCH 048/134] fix(deps): update dependency io.cucumber:cucumber-bom to v7.12.0 (#413) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3af99bd7..44f97f75 100644 --- a/pom.xml +++ b/pom.xml @@ -153,7 +153,7 @@ io.cucumber cucumber-bom - 7.11.2 + 7.12.0 pom import From 9d7d3d41f6a8e75b9a2b02e755a4c4048a3bc611 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 22:47:46 +0000 Subject: [PATCH 049/134] chore(deps): update codecov/codecov-action digest to 1dd0ce3 (#414) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 0f0d83f9..d1641345 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@894ff025c7b54547a9a2a1e9f228beae737ad3c2 + uses: codecov/codecov-action@1dd0ce34be62fac4f3b714f860c0b0c520acd35d with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 91f6ad24..5ca6f1fc 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@894ff025c7b54547a9a2a1e9f228beae737ad3c2 + uses: codecov/codecov-action@1dd0ce34be62fac4f3b714f860c0b0c520acd35d with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 0de764db19e793b81eeea345bcec8be6bc83b2b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 02:22:38 +0000 Subject: [PATCH 050/134] chore(deps): update github/codeql-action digest to 8ca5570 (#415) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 5ca6f1fc..74336f3f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@f31a31c052207cc13b328d6295c5b728bb49568c + uses: github/codeql-action/init@8ca5570701137b67af3d8ae3d6452f4cee6579da with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f31a31c052207cc13b328d6295c5b728bb49568c + uses: github/codeql-action/analyze@8ca5570701137b67af3d8ae3d6452f4cee6579da diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index b5b81b7a..a5c98eba 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f31a31c052207cc13b328d6295c5b728bb49568c + uses: github/codeql-action/init@8ca5570701137b67af3d8ae3d6452f4cee6579da with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@f31a31c052207cc13b328d6295c5b728bb49568c + uses: github/codeql-action/autobuild@8ca5570701137b67af3d8ae3d6452f4cee6579da - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f31a31c052207cc13b328d6295c5b728bb49568c + uses: github/codeql-action/analyze@8ca5570701137b67af3d8ae3d6452f4cee6579da From 19415edb713533d606b6483fb8fdfea4b838b133 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 May 2023 01:13:59 +0000 Subject: [PATCH 051/134] chore(deps): update codecov/codecov-action digest to 5bf2504 (#418) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index d1641345..745a31e8 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@1dd0ce34be62fac4f3b714f860c0b0c520acd35d + uses: codecov/codecov-action@5bf250470ea3e4bf9456e73127015eb78ce4c280 with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 74336f3f..df5df96b 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P integration-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@1dd0ce34be62fac4f3b714f860c0b0c520acd35d + uses: codecov/codecov-action@5bf250470ea3e4bf9456e73127015eb78ce4c280 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From a5c93aca0a718a5760bc346f27fd70b59432d11a Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 3 May 2023 00:36:22 -0400 Subject: [PATCH 052/134] chore: rename integration tests e2e (#417) * chore: rename integration tests e2e Signed-off-by: Todd Baert * Update pom.xml Co-authored-by: Giovanni Liva Signed-off-by: Todd Baert --------- Signed-off-by: Todd Baert Signed-off-by: Todd Baert Co-authored-by: Giovanni Liva --- .github/workflows/pullrequest.yml | 4 ++-- CONTRIBUTING.md | 6 +++--- pom.xml | 10 +++++----- .../sdk/{integration => e2e}/RunCucumberTest.java | 2 +- .../sdk/{integration => e2e}/StepDefinitions.java | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/test/java/dev/openfeature/sdk/{integration => e2e}/RunCucumberTest.java (92%) rename src/test/java/dev/openfeature/sdk/{integration => e2e}/StepDefinitions.java (99%) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index df5df96b..e0fe0dd9 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -38,8 +38,8 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - - name: Build with Maven - run: mvn --batch-mode --update-snapshots verify -P integration-test + - name: Verify with Maven + run: mvn --batch-mode --update-snapshots verify -P e2e-test - name: Upload coverage to Codecov uses: codecov/codecov-action@5bf250470ea3e4bf9456e73127015eb78ce4c280 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f18fa1af..b7ffa9a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,16 +16,16 @@ If you think we might be out of date with the spec, you can check that by invoki If you're adding tests to cover something in the spec, use the `@Specification` annotation like you see throughout the test suites. -## Integration tests +## End-to-End Tests -The continuous integration runs a set of [gherkin integration tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with +The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests do not run with the default maven profile. If you'd like to run them locally, you can start the flagd testbed with ``` docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest ``` and then run ``` -mvn test -P integration-test +mvn test -P e2e-test ``` ## Releasing diff --git a/pom.xml b/pom.xml index 44f97f75..db3608d3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,8 @@ 1.8 ${maven.compiler.source} 5.9.3 - - **/integration/*.java + + **/e2e/*.java ${groupId}.${artifactId} @@ -495,10 +495,10 @@ - - integration-test + + e2e-test - + diff --git a/src/test/java/dev/openfeature/sdk/integration/RunCucumberTest.java b/src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java similarity index 92% rename from src/test/java/dev/openfeature/sdk/integration/RunCucumberTest.java rename to src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java index 6a13ed29..2c652338 100644 --- a/src/test/java/dev/openfeature/sdk/integration/RunCucumberTest.java +++ b/src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java @@ -1,4 +1,4 @@ -package dev.openfeature.sdk.integration; +package dev.openfeature.sdk.e2e; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; diff --git a/src/test/java/dev/openfeature/sdk/integration/StepDefinitions.java b/src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java similarity index 99% rename from src/test/java/dev/openfeature/sdk/integration/StepDefinitions.java rename to src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java index 41c4dafc..7048fc0b 100644 --- a/src/test/java/dev/openfeature/sdk/integration/StepDefinitions.java +++ b/src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java @@ -1,4 +1,4 @@ -package dev.openfeature.sdk.integration; +package dev.openfeature.sdk.e2e; import dev.openfeature.contrib.providers.flagd.FlagdProvider; import dev.openfeature.sdk.Client; From 434da5a6080a8c3827a9a9cbb08ed98107c14264 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 21:55:39 -0700 Subject: [PATCH 053/134] chore(deps): update dependency dev.openfeature.contrib.providers:flagd to v0.5.9 (#416) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index db3608d3..3fcfb724 100644 --- a/pom.xml +++ b/pom.xml @@ -142,7 +142,7 @@ dev.openfeature.contrib.providers flagd - 0.5.8 + 0.5.9 test From b7dd2fc5a2ad9d00fb6500b1647ffb70dd539b45 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 May 2023 20:36:58 +0000 Subject: [PATCH 054/134] chore(deps): update codecov/codecov-action digest to b4dfea7 (#419) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 745a31e8..4bc20203 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@5bf250470ea3e4bf9456e73127015eb78ce4c280 + uses: codecov/codecov-action@b4dfea724ff5d8e51bb4dffdc668c0d964df6103 with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index e0fe0dd9..355c129b 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P e2e-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@5bf250470ea3e4bf9456e73127015eb78ce4c280 + uses: codecov/codecov-action@b4dfea724ff5d8e51bb4dffdc668c0d964df6103 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 42b931776a559fcc35ddee442d60bce6e86b16dd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 May 2023 07:11:17 +0000 Subject: [PATCH 055/134] chore(deps): update github/codeql-action digest to 318bcc7 (#420) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 355c129b..f6e3ee11 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@8ca5570701137b67af3d8ae3d6452f4cee6579da + uses: github/codeql-action/init@318bcc7f84641571687cf0178155b0e9693c0f45 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8ca5570701137b67af3d8ae3d6452f4cee6579da + uses: github/codeql-action/analyze@318bcc7f84641571687cf0178155b0e9693c0f45 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index a5c98eba..f8ae920e 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8ca5570701137b67af3d8ae3d6452f4cee6579da + uses: github/codeql-action/init@318bcc7f84641571687cf0178155b0e9693c0f45 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@8ca5570701137b67af3d8ae3d6452f4cee6579da + uses: github/codeql-action/autobuild@318bcc7f84641571687cf0178155b0e9693c0f45 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8ca5570701137b67af3d8ae3d6452f4cee6579da + uses: github/codeql-action/analyze@318bcc7f84641571687cf0178155b0e9693c0f45 From 7aade9a875245ededdb56597a89f4745f0d58622 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 May 2023 00:30:58 +0000 Subject: [PATCH 056/134] chore(deps): update github/codeql-action digest to 1e1aca8 (#421) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index f6e3ee11..b1afd784 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@318bcc7f84641571687cf0178155b0e9693c0f45 + uses: github/codeql-action/init@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@318bcc7f84641571687cf0178155b0e9693c0f45 + uses: github/codeql-action/analyze@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index f8ae920e..50931547 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@318bcc7f84641571687cf0178155b0e9693c0f45 + uses: github/codeql-action/init@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@318bcc7f84641571687cf0178155b0e9693c0f45 + uses: github/codeql-action/autobuild@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@318bcc7f84641571687cf0178155b0e9693c0f45 + uses: github/codeql-action/analyze@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b From af3e3d60dc12f37199e79a0f6dd5f7b065944a49 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 May 2023 03:26:36 +0000 Subject: [PATCH 057/134] chore(deps): update github/codeql-action digest to deb312c (#422) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index b1afd784..92ebae5d 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b + uses: github/codeql-action/init@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b + uses: github/codeql-action/analyze@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 50931547..292d4a75 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b + uses: github/codeql-action/init@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b + uses: github/codeql-action/autobuild@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1e1aca816581927cd0a1d4ade4bed45cd6e86b2b + uses: github/codeql-action/analyze@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc From 64f79cd513c698656eed2b10903b60ef3891c141 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 May 2023 12:16:28 +0000 Subject: [PATCH 058/134] chore(deps): update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.1.0 (#423) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3fcfb724..c8494ca5 100644 --- a/pom.xml +++ b/pom.xml @@ -400,7 +400,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts From 839fddb927575d92ed114518d9f2c16a92a0994b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 7 May 2023 23:59:37 +0000 Subject: [PATCH 059/134] chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.1.0 (#425) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c8494ca5..56c853e3 100644 --- a/pom.xml +++ b/pom.xml @@ -268,7 +268,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0 + 3.1.0 ${surefireArgLine} From 0ccf337384a3ffd286560ad29a3f4531998e8e2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 01:04:51 +0000 Subject: [PATCH 060/134] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.1.0 (#426) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 56c853e3..df68218d 100644 --- a/pom.xml +++ b/pom.xml @@ -250,7 +250,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.1.0 ${surefireArgLine} From 20628a23054768238cdef503382ee6b3c6d34476 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 00:49:52 +0000 Subject: [PATCH 061/134] chore(deps): update github/codeql-action digest to 95cfca7 (#427) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 92ebae5d..c090103d 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc + uses: github/codeql-action/init@95cfca769b334017179a1fbe879b6d9b5cddfe54 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc + uses: github/codeql-action/analyze@95cfca769b334017179a1fbe879b6d9b5cddfe54 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 292d4a75..7b163b45 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc + uses: github/codeql-action/init@95cfca769b334017179a1fbe879b6d9b5cddfe54 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc + uses: github/codeql-action/autobuild@95cfca769b334017179a1fbe879b6d9b5cddfe54 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@deb312c60b474a4b2a0f60399ae8fad9fa46e2bc + uses: github/codeql-action/analyze@95cfca769b334017179a1fbe879b6d9b5cddfe54 From 59d8a10ba311f7808a02db2773bad64356dda8e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 07:49:45 +0000 Subject: [PATCH 062/134] chore(deps): update codecov/codecov-action digest to cf8e3e4 (#428) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 4bc20203..4afa6234 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@b4dfea724ff5d8e51bb4dffdc668c0d964df6103 + uses: codecov/codecov-action@cf8e3e4262e63ac53fdbc0ea1b6dd69cb03c974b with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index c090103d..99adc19c 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P e2e-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@b4dfea724ff5d8e51bb4dffdc668c0d964df6103 + uses: codecov/codecov-action@cf8e3e4262e63ac53fdbc0ea1b6dd69cb03c974b with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 6405100b275f6465bbdcd25b5158ff6aad386f8b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 May 2023 19:55:18 +0000 Subject: [PATCH 063/134] chore(deps): update github/codeql-action digest to 130884e (#430) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 99adc19c..6f553e58 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@95cfca769b334017179a1fbe879b6d9b5cddfe54 + uses: github/codeql-action/init@130884e4e1961d7e595c85e8e60b206e0f5282e7 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95cfca769b334017179a1fbe879b6d9b5cddfe54 + uses: github/codeql-action/analyze@130884e4e1961d7e595c85e8e60b206e0f5282e7 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 7b163b45..19602ea6 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@95cfca769b334017179a1fbe879b6d9b5cddfe54 + uses: github/codeql-action/init@130884e4e1961d7e595c85e8e60b206e0f5282e7 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@95cfca769b334017179a1fbe879b6d9b5cddfe54 + uses: github/codeql-action/autobuild@130884e4e1961d7e595c85e8e60b206e0f5282e7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95cfca769b334017179a1fbe879b6d9b5cddfe54 + uses: github/codeql-action/analyze@130884e4e1961d7e595c85e8e60b206e0f5282e7 From 106df4661dd8e46da698ea4c90e8447aa958e6b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 00:11:40 +0000 Subject: [PATCH 064/134] chore(deps): update codecov/codecov-action digest to 49c20db (#431) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 4afa6234..968d57a7 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@cf8e3e4262e63ac53fdbc0ea1b6dd69cb03c974b + uses: codecov/codecov-action@49c20db375a254995f6d63d5dc03aa04e04a42ea with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 6f553e58..1f6c7d97 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P e2e-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@cf8e3e4262e63ac53fdbc0ea1b6dd69cb03c974b + uses: codecov/codecov-action@49c20db375a254995f6d63d5dc03aa04e04a42ea with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From aa495b28470d9a75bd64c148260b352dd8e6c6c2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 04:37:13 +0000 Subject: [PATCH 065/134] chore(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 (#432) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df68218d..c9c091b2 100644 --- a/pom.xml +++ b/pom.xml @@ -175,7 +175,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 validate From 3ff9995a437508ebb227c24e1c731dee447fc092 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 02:58:55 +0000 Subject: [PATCH 066/134] chore(deps): update codecov/codecov-action digest to eaaf4be (#433) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 968d57a7..74a2e9d7 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -49,7 +49,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify - name: Upload coverage to Codecov - uses: codecov/codecov-action@49c20db375a254995f6d63d5dc03aa04e04a42ea + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d with: flags: unittests # optional name: coverage # optional diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 1f6c7d97..6f2ef1a7 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -42,7 +42,7 @@ jobs: run: mvn --batch-mode --update-snapshots verify -P e2e-test - name: Upload coverage to Codecov - uses: codecov/codecov-action@49c20db375a254995f6d63d5dc03aa04e04a42ea + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional From 4d655900d94351de8700120acb90d4429e15a136 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 07:34:59 +0000 Subject: [PATCH 067/134] chore(deps): update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.21.0 (#434) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c9c091b2..d2f113d8 100644 --- a/pom.xml +++ b/pom.xml @@ -416,7 +416,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.20.0 + 3.21.0 run-pmd From 88e7d6054f60c15dc6f1130c4b6fe77be7098a5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 15:18:40 +0000 Subject: [PATCH 068/134] chore(deps): update amannn/action-semantic-pull-request digest to 3bb5af3 (#435) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/lint-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index afc537e4..28ce7e63 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -18,6 +18,6 @@ jobs: name: Validate PR title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@ff373f4e8056b732dfd0eadd42ae54c004e5523b + - uses: amannn/action-semantic-pull-request@3bb5af3c0c8f5e85d328728c1ab68dd6cefd03af env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 468c42d4e3902085cda852901097b5c197fd7906 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 23:52:01 +0000 Subject: [PATCH 069/134] chore(deps): update github/codeql-action digest to ca6b925 (#436) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 6f2ef1a7..ec1f722e 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@130884e4e1961d7e595c85e8e60b206e0f5282e7 + uses: github/codeql-action/init@ca6b92554892831c4507fde55f36bcd169fd7e01 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@130884e4e1961d7e595c85e8e60b206e0f5282e7 + uses: github/codeql-action/analyze@ca6b92554892831c4507fde55f36bcd169fd7e01 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 19602ea6..133ffdb9 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@130884e4e1961d7e595c85e8e60b206e0f5282e7 + uses: github/codeql-action/init@ca6b92554892831c4507fde55f36bcd169fd7e01 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@130884e4e1961d7e595c85e8e60b206e0f5282e7 + uses: github/codeql-action/autobuild@ca6b92554892831c4507fde55f36bcd169fd7e01 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@130884e4e1961d7e595c85e8e60b206e0f5282e7 + uses: github/codeql-action/analyze@ca6b92554892831c4507fde55f36bcd169fd7e01 From c3e82e97ddf071916b9c9e287bc935f5d177d01d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 03:23:10 +0000 Subject: [PATCH 070/134] chore(deps): update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.9 (#438) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d2f113d8..fbbd43ba 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.8 + 2.7.9 library 1.3 From 1af8e966a461d2eff40fdd3749df09e849339134 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 May 2023 17:42:57 +0000 Subject: [PATCH 071/134] chore(deps): update github/codeql-action digest to 6cfb483 (#439) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index ec1f722e..c88827b5 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@ca6b92554892831c4507fde55f36bcd169fd7e01 + uses: github/codeql-action/init@6cfb483131f3f74950a251876da81c79a6fcbdec with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ca6b92554892831c4507fde55f36bcd169fd7e01 + uses: github/codeql-action/analyze@6cfb483131f3f74950a251876da81c79a6fcbdec diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 133ffdb9..bdbc264d 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ca6b92554892831c4507fde55f36bcd169fd7e01 + uses: github/codeql-action/init@6cfb483131f3f74950a251876da81c79a6fcbdec with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@ca6b92554892831c4507fde55f36bcd169fd7e01 + uses: github/codeql-action/autobuild@6cfb483131f3f74950a251876da81c79a6fcbdec - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ca6b92554892831c4507fde55f36bcd169fd7e01 + uses: github/codeql-action/analyze@6cfb483131f3f74950a251876da81c79a6fcbdec From d4c43d74bc37371fc19dc1983e96e7c904d5a1e7 Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Fri, 19 May 2023 15:27:31 -0700 Subject: [PATCH 072/134] feat: Support mapping a client to a given provider. (#388) * Support mapping a client to a given provider. Signed-off-by: Justin Abrahms * Add a few javadocs. Signed-off-by: Justin Abrahms * Special case the null client name Signed-off-by: Justin Abrahms * Add some missing test cases. Signed-off-by: Justin Abrahms * Moving to an object map unwraps the values. Signed-off-by: Justin Abrahms * Fix equality test. Signed-off-by: Justin Abrahms * Carry targeting key when copying over null object. Signed-off-by: Justin Abrahms * Test provider name, not object equality. Signed-off-by: Justin Abrahms * Client-based getProvider is now an overload; Use read lock, not write lock. Signed-off-by: Justin Abrahms * Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java Co-authored-by: Lars Opitz Signed-off-by: Justin Abrahms * Simplify locking logic around providers. There's no such thing as "API without a provider set" anymore. We now default to NoOpProvider in the API (not client). Signed-off-by: Justin Abrahms * Add a few missing tests Signed-off-by: Justin Abrahms --------- Signed-off-by: Justin Abrahms Co-authored-by: Lars Opitz Co-authored-by: Michael Beemer --- .../dev/openfeature/sdk/MutableContext.java | 4 +- .../dev/openfeature/sdk/OpenFeatureAPI.java | 52 ++++++++++++++----- .../openfeature/sdk/OpenFeatureClient.java | 7 +-- .../sdk/ClientProviderMappingTest.java | 23 ++++++++ .../sdk/DeveloperExperienceTest.java | 9 ---- .../dev/openfeature/sdk/EvalContextTest.java | 7 +++ .../sdk/ImmutableStructureTest.java | 11 ++++ .../java/dev/openfeature/sdk/LockingTest.java | 9 ---- .../openfeature/sdk/OpenFeatureAPITest.java | 26 ++++++++++ .../sdk/OpenFeatureClientTest.java | 4 +- 10 files changed, 113 insertions(+), 39 deletions(-) create mode 100644 src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java create mode 100644 src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java diff --git a/src/main/java/dev/openfeature/sdk/MutableContext.java b/src/main/java/dev/openfeature/sdk/MutableContext.java index 6abd74a5..9e7069ca 100644 --- a/src/main/java/dev/openfeature/sdk/MutableContext.java +++ b/src/main/java/dev/openfeature/sdk/MutableContext.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -16,6 +17,7 @@ * be modified after instantiation. */ @ToString +@EqualsAndHashCode @SuppressWarnings("PMD.BeanMembersShouldSerialize") public class MutableContext implements EvaluationContext { @@ -88,7 +90,7 @@ public MutableContext add(String key, List value) { @Override public EvaluationContext merge(EvaluationContext overridingContext) { if (overridingContext == null) { - return new MutableContext(this.asMap()); + return new MutableContext(this.targetingKey, this.asMap()); } Map merged = this.merge(map -> new MutableStructure(map), diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java index e85f4e13..a2ddc453 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java @@ -1,8 +1,7 @@ package dev.openfeature.sdk; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; @@ -16,11 +15,11 @@ public class OpenFeatureAPI { // package-private multi-read/single-write lock static AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock(); - static AutoCloseableReentrantReadWriteLock providerLock = new AutoCloseableReentrantReadWriteLock(); static AutoCloseableReentrantReadWriteLock contextLock = new AutoCloseableReentrantReadWriteLock(); - private FeatureProvider provider; private EvaluationContext evaluationContext; - private List apiHooks; + private final List apiHooks; + private FeatureProvider defaultProvider = new NoOpProvider(); + private final Map providers = new ConcurrentHashMap<>(); private OpenFeatureAPI() { this.apiHooks = new ArrayList<>(); @@ -39,7 +38,11 @@ public static OpenFeatureAPI getInstance() { } public Metadata getProviderMetadata() { - return provider.getMetadata(); + return defaultProvider.getMetadata(); + } + + public Metadata getProviderMetadata(String clientName) { + return getProvider(clientName).getMetadata(); } public Client getClient() { @@ -73,23 +76,44 @@ public EvaluationContext getEvaluationContext() { } /** - * {@inheritDoc} + * Set the default provider. */ public void setProvider(FeatureProvider provider) { - try (AutoCloseableLock __ = providerLock.writeLockAutoCloseable()) { - this.provider = provider; + if (provider == null) { + throw new IllegalArgumentException("Provider cannot be null"); } + defaultProvider = provider; } /** - * {@inheritDoc} + * Add a provider for a named client. + * @param clientName The name of the client. + * @param provider The provider to set. */ - public FeatureProvider getProvider() { - try (AutoCloseableLock __ = providerLock.readLockAutoCloseable()) { - return this.provider; + public void setProvider(String clientName, FeatureProvider provider) { + if (provider == null) { + throw new IllegalArgumentException("Provider cannot be null"); } + this.providers.put(clientName, provider); } + /** + * Return the default provider. + */ + public FeatureProvider getProvider() { + return defaultProvider; + } + + /** + * Fetch a provider for a named client. If not found, return the default. + * @param name The client name to look for. + * @return A named {@link FeatureProvider} + */ + public FeatureProvider getProvider(String name) { + return Optional.ofNullable(name).map(this.providers::get).orElse(defaultProvider); + } + + /** * {@inheritDoc} */ diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java index a13eb942..44febf77 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java @@ -99,17 +99,14 @@ private FlagEvaluationDetails evaluateFlag(FlagValueType type, String key FlagEvaluationDetails details = null; List mergedHooks = null; HookContext hookCtx = null; - FeatureProvider provider = null; + FeatureProvider provider; try { final EvaluationContext apiContext; final EvaluationContext clientContext; // openfeatureApi.getProvider() must be called once to maintain a consistent reference - provider = ObjectUtils.defaultIfNull(openfeatureApi.getProvider(), () -> { - log.debug("No provider configured, using no-op provider."); - return new NoOpProvider(); - }); + provider = openfeatureApi.getProvider(this.name); mergedHooks = ObjectUtils.merge(provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getHooks()); diff --git a/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java b/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java new file mode 100644 index 00000000..654fb335 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java @@ -0,0 +1,23 @@ +package dev.openfeature.sdk; + +import io.cucumber.java.eo.Do; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ClientProviderMappingTest { + @Test + void clientProviderTest() { + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + + api.setProvider("client1", new DoSomethingProvider()); + api.setProvider("client2", new NoOpProvider()); + + Client c1 = api.getClient("client1"); + Client c2 = api.getClient("client2"); + + assertTrue(c1.getBooleanValue("test", false)); + assertFalse(c2.getBooleanValue("test", false)); + } +} diff --git a/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java b/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java index f32711a2..600dc7a6 100644 --- a/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java +++ b/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java @@ -19,15 +19,6 @@ class DeveloperExperienceTest implements HookFixtures { transient String flagKey = "mykey"; - @Test void noProviderSet() { - final String noOp = "no-op"; - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(null); - Client client = api.getClient(); - String retval = client.getStringValue(flagKey, noOp); - assertEquals(noOp, retval); - } - @Test void simpleBooleanFlag() { OpenFeatureAPI api = OpenFeatureAPI.getInstance(); api.setProvider(new NoOpProvider()); diff --git a/src/test/java/dev/openfeature/sdk/EvalContextTest.java b/src/test/java/dev/openfeature/sdk/EvalContextTest.java index 29fd0898..f4cd804c 100644 --- a/src/test/java/dev/openfeature/sdk/EvalContextTest.java +++ b/src/test/java/dev/openfeature/sdk/EvalContextTest.java @@ -162,6 +162,13 @@ public class EvalContextTest { assertEquals(key1, ctxMerged.getTargetingKey()); } + @Test void merge_null_returns_value() { + MutableContext ctx1 = new MutableContext("key"); + ctx1.add("mything", "value"); + EvaluationContext result = ctx1.merge(null); + assertEquals(ctx1, result); + } + @Test void merge_targeting_key() { String key1 = "key1"; MutableContext ctx1 = new MutableContext(key1); diff --git a/src/test/java/dev/openfeature/sdk/ImmutableStructureTest.java b/src/test/java/dev/openfeature/sdk/ImmutableStructureTest.java index 49cd236a..d7453452 100644 --- a/src/test/java/dev/openfeature/sdk/ImmutableStructureTest.java +++ b/src/test/java/dev/openfeature/sdk/ImmutableStructureTest.java @@ -111,4 +111,15 @@ void GettingAMissingValueShouldReturnNull() { Object value = structure.getValue("missing"); assertNull(value); } + + @Test void objectMapTest() { + Map attrs = new HashMap<>(); + attrs.put("test", new Value(45)); + ImmutableStructure structure = new ImmutableStructure(attrs); + + Map expected = new HashMap<>(); + expected.put("test", 45); + + assertEquals(expected, structure.asObjectMap()); + } } diff --git a/src/test/java/dev/openfeature/sdk/LockingTest.java b/src/test/java/dev/openfeature/sdk/LockingTest.java index f8dceee6..3d8d90c8 100644 --- a/src/test/java/dev/openfeature/sdk/LockingTest.java +++ b/src/test/java/dev/openfeature/sdk/LockingTest.java @@ -19,7 +19,6 @@ class LockingTest { private OpenFeatureClient client; private AutoCloseableReentrantReadWriteLock apiContextLock; private AutoCloseableReentrantReadWriteLock apiHooksLock; - private AutoCloseableReentrantReadWriteLock apiProviderLock; private AutoCloseableReentrantReadWriteLock clientContextLock; private AutoCloseableReentrantReadWriteLock clientHooksLock; @@ -33,10 +32,8 @@ void beforeEach() { client = (OpenFeatureClient) api.getClient(); apiContextLock = setupLock(apiContextLock, mockInnerReadLock(), mockInnerWriteLock()); - apiProviderLock = setupLock(apiProviderLock, mockInnerReadLock(), mockInnerWriteLock()); apiHooksLock = setupLock(apiHooksLock, mockInnerReadLock(), mockInnerWriteLock()); OpenFeatureAPI.contextLock = apiContextLock; - OpenFeatureAPI.providerLock = apiProviderLock; OpenFeatureAPI.hooksLock = apiHooksLock; clientContextLock = setupLock(clientContextLock, mockInnerReadLock(), mockInnerWriteLock()); @@ -91,12 +88,6 @@ void getContextShouldReadLockAndUnlock() { verify(apiContextLock.readLock()).unlock(); } - @Test - void setProviderShouldWriteLockAndUnlock() { - api.setProvider(new DoSomethingProvider()); - verify(apiProviderLock.writeLock()).lock(); - verify(apiProviderLock.writeLock()).unlock(); - } @Test void clearHooksShouldWriteLockAndUnlock() { diff --git a/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java b/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java new file mode 100644 index 00000000..4428f9ff --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java @@ -0,0 +1,26 @@ +package dev.openfeature.sdk; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class OpenFeatureAPITest { + @Test + void namedProviderTest() { + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + FeatureProvider provider = new NoOpProvider(); + api.setProvider("namedProviderTest", provider); + assertEquals(provider.getMetadata().getName(), api.getProviderMetadata("namedProviderTest").getName()); + } + + @Test void settingDefaultProviderToNullErrors() { + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + assertThrows(IllegalArgumentException.class, () -> api.setProvider(null)); + } + + @Test void settingNamedClientProviderToNullErrors() { + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + assertThrows(IllegalArgumentException.class, () -> api.setProvider("client-name", null)); + } +} diff --git a/src/test/java/dev/openfeature/sdk/OpenFeatureClientTest.java b/src/test/java/dev/openfeature/sdk/OpenFeatureClientTest.java index ac150677..9036576d 100644 --- a/src/test/java/dev/openfeature/sdk/OpenFeatureClientTest.java +++ b/src/test/java/dev/openfeature/sdk/OpenFeatureClientTest.java @@ -27,7 +27,7 @@ class OpenFeatureClientTest implements HookFixtures { @DisplayName("should not throw exception if hook has different type argument than hookContext") void shouldNotThrowExceptionIfHookHasDifferentTypeArgumentThanHookContext() { OpenFeatureAPI api = mock(OpenFeatureAPI.class); - when(api.getProvider()).thenReturn(new DoSomethingProvider()); + when(api.getProvider(any())).thenReturn(new DoSomethingProvider()); when(api.getHooks()).thenReturn(Arrays.asList(mockBooleanHook(), mockStringHook())); OpenFeatureClient client = new OpenFeatureClient(api, "name", "version"); @@ -57,6 +57,8 @@ void mergeContextTest() { context -> context.getTargetingKey().equals(targetingKey)))).thenReturn(ProviderEvaluation.builder() .value(true).build()); when(api.getProvider()).thenReturn(mockProvider); + when(api.getProvider(any())).thenReturn(mockProvider); + OpenFeatureClient client = new OpenFeatureClient(api, "name", "version"); client.setEvaluationContext(ctx); From bcbaff8e4f15122d7e083ce68af7c0446adaf9fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 21 May 2023 11:44:10 +0000 Subject: [PATCH 073/134] chore(deps): update dependency org.apache.maven.plugins:maven-source-plugin to v3.3.0 (#443) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fbbd43ba..aabf08af 100644 --- a/pom.xml +++ b/pom.xml @@ -366,7 +366,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources From 5388fa12b61d127588aca02999d26bc3c9986b1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 21 May 2023 11:00:17 -0700 Subject: [PATCH 074/134] chore(deps): update dependency dev.openfeature.contrib.providers:flagd to v0.5.10 (#429) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aabf08af..f68053a3 100644 --- a/pom.xml +++ b/pom.xml @@ -142,7 +142,7 @@ dev.openfeature.contrib.providers flagd - 0.5.9 + 0.5.10 test From f9523ecd8b4585619ea6e12caffcb90c42eb354c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 18:37:20 +0000 Subject: [PATCH 075/134] chore(deps): update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.3.0 (#444) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f68053a3..eff466ac 100644 --- a/pom.xml +++ b/pom.xml @@ -464,7 +464,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.2.2 + 3.3.0 checkstyle.xml UTF-8 From e393b64715f27cd96a1823c537c6d4c58030e0a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 23:43:19 +0000 Subject: [PATCH 076/134] chore(deps): update github/codeql-action digest to 1245696 (#446) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index c88827b5..d4e2be84 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@6cfb483131f3f74950a251876da81c79a6fcbdec + uses: github/codeql-action/init@1245696032ecf7d39f87d54daa406e22ddf769a8 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6cfb483131f3f74950a251876da81c79a6fcbdec + uses: github/codeql-action/analyze@1245696032ecf7d39f87d54daa406e22ddf769a8 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index bdbc264d..a41f95d8 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6cfb483131f3f74950a251876da81c79a6fcbdec + uses: github/codeql-action/init@1245696032ecf7d39f87d54daa406e22ddf769a8 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@6cfb483131f3f74950a251876da81c79a6fcbdec + uses: github/codeql-action/autobuild@1245696032ecf7d39f87d54daa406e22ddf769a8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6cfb483131f3f74950a251876da81c79a6fcbdec + uses: github/codeql-action/analyze@1245696032ecf7d39f87d54daa406e22ddf769a8 From eb6f9e69ef8729d2850f8c1e63a66f30c0a8dd51 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 02:33:52 +0000 Subject: [PATCH 077/134] chore(deps): update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.6.0 (#445) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eff466ac..deaf7588 100644 --- a/pom.xml +++ b/pom.xml @@ -215,7 +215,7 @@ maven-dependency-plugin - 3.5.0 + 3.6.0 verify From dfb214c52f89a84becd170925721179a2ff24c75 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 05:21:21 +0000 Subject: [PATCH 078/134] fix(deps): update dependency org.projectlombok:lombok to v1.18.28 (#448) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index deaf7588..3b1f258d 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ org.projectlombok lombok - 1.18.26 + 1.18.28 provided From 8d675ca38751e9c7bb8c7dd74591b9992cb696ec Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 07:35:01 +0000 Subject: [PATCH 079/134] chore(deps): update github/codeql-action digest to 11ea309 (#447) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d4e2be84..dd9f5aab 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@1245696032ecf7d39f87d54daa406e22ddf769a8 + uses: github/codeql-action/init@11ea309db5eceb7702c247f78371f8180fa6545e with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1245696032ecf7d39f87d54daa406e22ddf769a8 + uses: github/codeql-action/analyze@11ea309db5eceb7702c247f78371f8180fa6545e diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index a41f95d8..346c636b 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1245696032ecf7d39f87d54daa406e22ddf769a8 + uses: github/codeql-action/init@11ea309db5eceb7702c247f78371f8180fa6545e with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@1245696032ecf7d39f87d54daa406e22ddf769a8 + uses: github/codeql-action/autobuild@11ea309db5eceb7702c247f78371f8180fa6545e - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1245696032ecf7d39f87d54daa406e22ddf769a8 + uses: github/codeql-action/analyze@11ea309db5eceb7702c247f78371f8180fa6545e From 79222e1cf7223ceee75f587804904492ca004b74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 14:19:30 +0000 Subject: [PATCH 080/134] chore(deps): update github/codeql-action digest to 5f061ca (#450) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index dd9f5aab..d2b7dfd4 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@11ea309db5eceb7702c247f78371f8180fa6545e + uses: github/codeql-action/init@5f061ca665a73932294894cbe96acaefb03297cd with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@11ea309db5eceb7702c247f78371f8180fa6545e + uses: github/codeql-action/analyze@5f061ca665a73932294894cbe96acaefb03297cd diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 346c636b..cfeaf0ed 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@11ea309db5eceb7702c247f78371f8180fa6545e + uses: github/codeql-action/init@5f061ca665a73932294894cbe96acaefb03297cd with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@11ea309db5eceb7702c247f78371f8180fa6545e + uses: github/codeql-action/autobuild@5f061ca665a73932294894cbe96acaefb03297cd - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@11ea309db5eceb7702c247f78371f8180fa6545e + uses: github/codeql-action/analyze@5f061ca665a73932294894cbe96acaefb03297cd From fa1e14451d04663dabc314e25e6ddf5ba1fb2ecf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 01:26:40 +0000 Subject: [PATCH 081/134] chore(deps): update github/codeql-action digest to 2d031a3 (#451) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d2b7dfd4..629cb8c3 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@5f061ca665a73932294894cbe96acaefb03297cd + uses: github/codeql-action/init@2d031a36d6d4956b5165162600cde125e59757d9 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5f061ca665a73932294894cbe96acaefb03297cd + uses: github/codeql-action/analyze@2d031a36d6d4956b5165162600cde125e59757d9 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index cfeaf0ed..6ce2e8c4 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5f061ca665a73932294894cbe96acaefb03297cd + uses: github/codeql-action/init@2d031a36d6d4956b5165162600cde125e59757d9 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@5f061ca665a73932294894cbe96acaefb03297cd + uses: github/codeql-action/autobuild@2d031a36d6d4956b5165162600cde125e59757d9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5f061ca665a73932294894cbe96acaefb03297cd + uses: github/codeql-action/analyze@2d031a36d6d4956b5165162600cde125e59757d9 From 58df782b767617c63628ddb9ece3ed3816d865ad Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 05:33:15 +0000 Subject: [PATCH 082/134] chore(deps): update google-github-actions/release-please-action digest to 51ee8ae (#452) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d55722b5..f9e7739e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@84759371f245a9245d04f684a8207ced70852d7e + - uses: google-github-actions/release-please-action@51ee8ae2605bd5ce1cfdcc5938684908f1cd9f69 id: release with: command: manifest From 1dddd68c4243a8823bb1b92091d3b25871e50ed8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 17:13:30 +0000 Subject: [PATCH 083/134] chore(deps): update github/codeql-action digest to f8b1cb6 (#453) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 629cb8c3..43dabde3 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@2d031a36d6d4956b5165162600cde125e59757d9 + uses: github/codeql-action/init@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2d031a36d6d4956b5165162600cde125e59757d9 + uses: github/codeql-action/analyze@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 6ce2e8c4..c3644c2d 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@2d031a36d6d4956b5165162600cde125e59757d9 + uses: github/codeql-action/init@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@2d031a36d6d4956b5165162600cde125e59757d9 + uses: github/codeql-action/autobuild@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2d031a36d6d4956b5165162600cde125e59757d9 + uses: github/codeql-action/analyze@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 From cc155b354c4978274d386eb769260f02535bc198 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 27 May 2023 01:25:06 +0000 Subject: [PATCH 084/134] chore(deps): update github/codeql-action digest to 6bd8101 (#454) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 43dabde3..a9ff9f2e 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 + uses: github/codeql-action/init@6bd81017529439c8f8ebf8710a35939036c8c30e with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 + uses: github/codeql-action/analyze@6bd81017529439c8f8ebf8710a35939036c8c30e diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index c3644c2d..1901e7ec 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 + uses: github/codeql-action/init@6bd81017529439c8f8ebf8710a35939036c8c30e with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 + uses: github/codeql-action/autobuild@6bd81017529439c8f8ebf8710a35939036c8c30e - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f8b1cb6997ca27fd7fd2311ede5bafd94cb27c44 + uses: github/codeql-action/analyze@6bd81017529439c8f8ebf8710a35939036c8c30e From e1a0432ae988c5311bc00008fd3e8687d3a3839f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 15:19:24 +0000 Subject: [PATCH 085/134] chore(deps): update github/codeql-action digest to 9d2dd7c (#457) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index a9ff9f2e..4e538d79 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@6bd81017529439c8f8ebf8710a35939036c8c30e + uses: github/codeql-action/init@9d2dd7cfeadb2b1cd7a048aa17251e221791941e with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bd81017529439c8f8ebf8710a35939036c8c30e + uses: github/codeql-action/analyze@9d2dd7cfeadb2b1cd7a048aa17251e221791941e diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 1901e7ec..286b888f 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6bd81017529439c8f8ebf8710a35939036c8c30e + uses: github/codeql-action/init@9d2dd7cfeadb2b1cd7a048aa17251e221791941e with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@6bd81017529439c8f8ebf8710a35939036c8c30e + uses: github/codeql-action/autobuild@9d2dd7cfeadb2b1cd7a048aa17251e221791941e - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bd81017529439c8f8ebf8710a35939036c8c30e + uses: github/codeql-action/analyze@9d2dd7cfeadb2b1cd7a048aa17251e221791941e From 401d7a8a5fe19835710eadce3fa88a2fcb0ee5c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 22:46:18 +0000 Subject: [PATCH 086/134] chore(deps): update github/codeql-action digest to 96f2840 (#458) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4e538d79..732d7e56 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@9d2dd7cfeadb2b1cd7a048aa17251e221791941e + uses: github/codeql-action/init@96f284028262d223858647b5680642a84608cc87 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9d2dd7cfeadb2b1cd7a048aa17251e221791941e + uses: github/codeql-action/analyze@96f284028262d223858647b5680642a84608cc87 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 286b888f..d95da05a 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9d2dd7cfeadb2b1cd7a048aa17251e221791941e + uses: github/codeql-action/init@96f284028262d223858647b5680642a84608cc87 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@9d2dd7cfeadb2b1cd7a048aa17251e221791941e + uses: github/codeql-action/autobuild@96f284028262d223858647b5680642a84608cc87 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9d2dd7cfeadb2b1cd7a048aa17251e221791941e + uses: github/codeql-action/analyze@96f284028262d223858647b5680642a84608cc87 From 0b1315eaaf4cb36bfb6c45a31d337e3ae31c0ea5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 22:56:23 +0000 Subject: [PATCH 087/134] chore(deps): update github/codeql-action digest to 926a489 (#460) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 732d7e56..f82c19a6 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@96f284028262d223858647b5680642a84608cc87 + uses: github/codeql-action/init@926a4898bc8705cbb609517ff5086b235af7c1aa with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@96f284028262d223858647b5680642a84608cc87 + uses: github/codeql-action/analyze@926a4898bc8705cbb609517ff5086b235af7c1aa diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index d95da05a..c1b5292c 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@96f284028262d223858647b5680642a84608cc87 + uses: github/codeql-action/init@926a4898bc8705cbb609517ff5086b235af7c1aa with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@96f284028262d223858647b5680642a84608cc87 + uses: github/codeql-action/autobuild@926a4898bc8705cbb609517ff5086b235af7c1aa - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@96f284028262d223858647b5680642a84608cc87 + uses: github/codeql-action/analyze@926a4898bc8705cbb609517ff5086b235af7c1aa From c26b75593edaf3a6f87c85bb9065ec485612c723 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 19:14:30 +0000 Subject: [PATCH 088/134] fix(deps): update dependency io.cucumber:cucumber-bom to v7.12.1 (#461) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3b1f258d..3c80d36d 100644 --- a/pom.xml +++ b/pom.xml @@ -153,7 +153,7 @@ io.cucumber cucumber-bom - 7.12.0 + 7.12.1 pom import From 7f9194231c6340a712a23b7298772fba3b4f4824 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 22:03:20 +0000 Subject: [PATCH 089/134] chore(deps): update github/codeql-action digest to 8b0f2cf (#462) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index f82c19a6..fff4c076 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@926a4898bc8705cbb609517ff5086b235af7c1aa + uses: github/codeql-action/init@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@926a4898bc8705cbb609517ff5086b235af7c1aa + uses: github/codeql-action/analyze@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index c1b5292c..f1433d31 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@926a4898bc8705cbb609517ff5086b235af7c1aa + uses: github/codeql-action/init@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@926a4898bc8705cbb609517ff5086b235af7c1aa + uses: github/codeql-action/autobuild@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@926a4898bc8705cbb609517ff5086b235af7c1aa + uses: github/codeql-action/analyze@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f From 736cf24cbf54680c7c9ce66b05ef74402743f899 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 22:02:51 +0000 Subject: [PATCH 090/134] chore(deps): update github/codeql-action digest to cdcdbb5 (#463) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index fff4c076..f91efa05 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index f1433d31..dfebe829 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f + uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8b0f2cf9da2c81396ee1b93eb705dd70e30e254f + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a From 24f092319dfade89b2a6a62b86cce2d88b81fa3a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 01:06:43 +0000 Subject: [PATCH 091/134] chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.1.2 (#464) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3c80d36d..abfdc2d5 100644 --- a/pom.xml +++ b/pom.xml @@ -268,7 +268,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.1.0 + 3.1.2 ${surefireArgLine} From 5f173ff8607e8430bf14a57e7782dc0e8460317a Mon Sep 17 00:00:00 2001 From: Lars Opitz Date: Wed, 7 Jun 2023 03:36:47 +0200 Subject: [PATCH 092/134] feat: add initialize and shutdown behavior (#456) Signed-off-by: Lars Opitz Co-authored-by: Todd Baert --- pom.xml | 7 + .../dev/openfeature/sdk/FeatureProvider.java | 25 ++ .../dev/openfeature/sdk/OpenFeatureAPI.java | 54 ++- .../openfeature/sdk/ProviderRepository.java | 156 +++++++ .../sdk/ClientProviderMappingTest.java | 12 +- .../sdk/DeveloperExperienceTest.java | 9 +- .../sdk/FlagEvaluationSpecTest.java | 53 +-- .../dev/openfeature/sdk/HookSpecTest.java | 27 +- .../sdk/InitializeBehaviorSpecTest.java | 81 ++++ .../openfeature/sdk/OpenFeatureAPITest.java | 37 +- .../sdk/ProviderRepositoryTest.java | 425 ++++++++++++++++++ .../sdk/ShutdownBehaviorSpecTest.java | 117 +++++ .../sdk/fixtures/ProviderFixture.java | 43 ++ .../testutils/FeatureProviderTestUtils.java | 30 ++ .../testutils/exception/TestException.java | 9 + .../testutils/stubbing/ConditionStubber.java | 37 ++ 16 files changed, 1032 insertions(+), 90 deletions(-) create mode 100644 src/main/java/dev/openfeature/sdk/ProviderRepository.java create mode 100644 src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java create mode 100644 src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java create mode 100644 src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java create mode 100644 src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java create mode 100644 src/test/java/dev/openfeature/sdk/testutils/FeatureProviderTestUtils.java create mode 100644 src/test/java/dev/openfeature/sdk/testutils/exception/TestException.java create mode 100644 src/test/java/dev/openfeature/sdk/testutils/stubbing/ConditionStubber.java diff --git a/pom.xml b/pom.xml index abfdc2d5..26cb9329 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,13 @@ 0.5.10 test + + + org.awaitility + awaitility + 4.2.0 + test + diff --git a/src/main/java/dev/openfeature/sdk/FeatureProvider.java b/src/main/java/dev/openfeature/sdk/FeatureProvider.java index 77e9cd67..7df56a5f 100644 --- a/src/main/java/dev/openfeature/sdk/FeatureProvider.java +++ b/src/main/java/dev/openfeature/sdk/FeatureProvider.java @@ -22,4 +22,29 @@ default List getProviderHooks() { ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx); ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx); + + /** + * This method is called before a provider is used to evaluate flags. Providers can overwrite this method, + * if they have special initialization needed prior being called for flag evaluation. + *

+ * It is ok, if the method is expensive as it is executed in the background. All runtime exceptions will be + * caught and logged. + *

+ */ + default void initialize() { + // Intentionally left blank + } + + /** + * This method is called when a new provider is about to be used to evaluate flags, or the SDK is shut down. + * Providers can overwrite this method, if they have special shutdown actions needed. + *

+ * It is ok, if the method is expensive as it is executed in the background. All runtime exceptions will be + * caught and logged. + *

+ */ + default void shutdown() { + // Intentionally left blank + } + } diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java index a2ddc453..2e921a74 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java @@ -1,27 +1,30 @@ package dev.openfeature.sdk; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import javax.annotation.Nullable; - import dev.openfeature.sdk.internal.AutoCloseableLock; import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * A global singleton which holds base configuration for the OpenFeature library. * Configuration here will be shared across all {@link Client}s. */ +@Slf4j public class OpenFeatureAPI { // package-private multi-read/single-write lock static AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock(); static AutoCloseableReentrantReadWriteLock contextLock = new AutoCloseableReentrantReadWriteLock(); - private EvaluationContext evaluationContext; + private final List apiHooks; - private FeatureProvider defaultProvider = new NoOpProvider(); - private final Map providers = new ConcurrentHashMap<>(); - private OpenFeatureAPI() { + private ProviderRepository providerRepository = new ProviderRepository(); + private EvaluationContext evaluationContext; + + protected OpenFeatureAPI() { this.apiHooks = new ArrayList<>(); } @@ -31,6 +34,7 @@ private static class SingletonHolder { /** * Provisions the {@link OpenFeatureAPI} singleton (if needed) and returns it. + * * @return The singleton instance. */ public static OpenFeatureAPI getInstance() { @@ -38,7 +42,7 @@ public static OpenFeatureAPI getInstance() { } public Metadata getProviderMetadata() { - return defaultProvider.getMetadata(); + return getProvider().getMetadata(); } public Metadata getProviderMetadata(String clientName) { @@ -79,41 +83,36 @@ public EvaluationContext getEvaluationContext() { * Set the default provider. */ public void setProvider(FeatureProvider provider) { - if (provider == null) { - throw new IllegalArgumentException("Provider cannot be null"); - } - defaultProvider = provider; + providerRepository.setProvider(provider); } /** * Add a provider for a named client. + * * @param clientName The name of the client. - * @param provider The provider to set. + * @param provider The provider to set. */ public void setProvider(String clientName, FeatureProvider provider) { - if (provider == null) { - throw new IllegalArgumentException("Provider cannot be null"); - } - this.providers.put(clientName, provider); + providerRepository.setProvider(clientName, provider); } /** * Return the default provider. */ public FeatureProvider getProvider() { - return defaultProvider; + return providerRepository.getProvider(); } /** * Fetch a provider for a named client. If not found, return the default. + * * @param name The client name to look for. * @return A named {@link FeatureProvider} */ public FeatureProvider getProvider(String name) { - return Optional.ofNullable(name).map(this.providers::get).orElse(defaultProvider); + return providerRepository.getProvider(name); } - /** * {@inheritDoc} */ @@ -140,4 +139,15 @@ public void clearHooks() { this.apiHooks.clear(); } } + + public void shutdown() { + providerRepository.shutdown(); + } + + /** + * This method is only here for testing as otherwise all tests after the API shutdown test would fail. + */ + final void resetProviderRepository() { + providerRepository = new ProviderRepository(); + } } diff --git a/src/main/java/dev/openfeature/sdk/ProviderRepository.java b/src/main/java/dev/openfeature/sdk/ProviderRepository.java new file mode 100644 index 00000000..5a360eb6 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/ProviderRepository.java @@ -0,0 +1,156 @@ +package dev.openfeature.sdk; + +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.stream.Stream; + +@Slf4j +class ProviderRepository { + + private final Map providers = new ConcurrentHashMap<>(); + private final ExecutorService taskExecutor = Executors.newCachedThreadPool(); + private final Map initializingNamedProviders = new ConcurrentHashMap<>(); + private final AtomicReference defaultProvider = new AtomicReference<>(new NoOpProvider()); + private FeatureProvider initializingDefaultProvider; + + /** + * Return the default provider. + */ + public FeatureProvider getProvider() { + return defaultProvider.get(); + } + + /** + * Fetch a provider for a named client. If not found, return the default. + * + * @param name The client name to look for. + * @return A named {@link FeatureProvider} + */ + public FeatureProvider getProvider(String name) { + return Optional.ofNullable(name).map(this.providers::get).orElse(this.defaultProvider.get()); + } + + /** + * Set the default provider. + */ + public void setProvider(FeatureProvider provider) { + if (provider == null) { + throw new IllegalArgumentException("Provider cannot be null"); + } + initializeProvider(provider); + } + + /** + * Add a provider for a named client. + * + * @param clientName The name of the client. + * @param provider The provider to set. + */ + public void setProvider(String clientName, FeatureProvider provider) { + if (provider == null) { + throw new IllegalArgumentException("Provider cannot be null"); + } + if (clientName == null) { + throw new IllegalArgumentException("clientName cannot be null"); + } + initializeProvider(clientName, provider); + } + + private void initializeProvider(FeatureProvider provider) { + initializingDefaultProvider = provider; + initializeProvider(provider, this::updateDefaultProviderAfterInitialization); + } + + private void initializeProvider(String clientName, FeatureProvider provider) { + initializingNamedProviders.put(clientName, provider); + initializeProvider(provider, newProvider -> updateProviderAfterInit(clientName, newProvider)); + } + + private void initializeProvider(FeatureProvider provider, Consumer afterInitialization) { + taskExecutor.submit(() -> { + try { + if (!isProviderRegistered(provider)) { + provider.initialize(); + } + afterInitialization.accept(provider); + } catch (Exception e) { + log.error("Exception when initializing feature provider {}", provider.getClass().getName(), e); + } + }); + } + + private void updateProviderAfterInit(String clientName, FeatureProvider newProvider) { + Optional + .ofNullable(initializingNamedProviders.get(clientName)) + .filter(initializingProvider -> initializingProvider.equals(newProvider)) + .ifPresent(provider -> updateNamedProviderAfterInitialization(clientName, provider)); + } + + private void updateDefaultProviderAfterInitialization(FeatureProvider initializedProvider) { + Optional + .ofNullable(this.initializingDefaultProvider) + .filter(initializingProvider -> initializingProvider.equals(initializedProvider)) + .ifPresent(this::replaceDefaultProvider); + } + + private void replaceDefaultProvider(FeatureProvider provider) { + FeatureProvider oldProvider = this.defaultProvider.getAndSet(provider); + if (isOldProviderNotBoundByName(oldProvider)) { + shutdownProvider(oldProvider); + } + } + + private boolean isOldProviderNotBoundByName(FeatureProvider oldProvider) { + return !this.providers.containsValue(oldProvider); + } + + private void updateNamedProviderAfterInitialization(String clientName, FeatureProvider initializedProvider) { + Optional + .ofNullable(this.initializingNamedProviders.get(clientName)) + .filter(initializingProvider -> initializingProvider.equals(initializedProvider)) + .ifPresent(provider -> replaceNamedProviderAndShutdownOldOne(clientName, provider)); + } + + private void replaceNamedProviderAndShutdownOldOne(String clientName, FeatureProvider provider) { + FeatureProvider oldProvider = this.providers.put(clientName, provider); + this.initializingNamedProviders.remove(clientName, provider); + if (!isProviderRegistered(oldProvider)) { + shutdownProvider(oldProvider); + } + } + + private boolean isProviderRegistered(FeatureProvider oldProvider) { + return this.providers.containsValue(oldProvider) || this.defaultProvider.get().equals(oldProvider); + } + + private void shutdownProvider(FeatureProvider provider) { + taskExecutor.submit(() -> { + try { + provider.shutdown(); + } catch (Exception e) { + log.error("Exception when shutting down feature provider {}", provider.getClass().getName(), e); + } + }); + } + + /** + * Shutdowns this repository which includes shutting down all FeatureProviders that are registered, + * including the default feature provider. + */ + public void shutdown() { + Stream + .concat(Stream.of(this.defaultProvider.get()), this.providers.values().stream()) + .distinct() + .forEach(this::shutdownProvider); + setProvider(new NoOpProvider()); + this.providers.clear(); + taskExecutor.shutdown(); + } +} diff --git a/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java b/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java index 654fb335..8f022a38 100644 --- a/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java +++ b/src/test/java/dev/openfeature/sdk/ClientProviderMappingTest.java @@ -1,18 +1,18 @@ package dev.openfeature.sdk; -import io.cucumber.java.eo.Do; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; + +class ClientProviderMappingTest { -public class ClientProviderMappingTest { @Test void clientProviderTest() { OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider("client1", new DoSomethingProvider()); - api.setProvider("client2", new NoOpProvider()); + FeatureProviderTestUtils.setFeatureProvider("client1", new DoSomethingProvider()); + FeatureProviderTestUtils.setFeatureProvider("client2", new NoOpProvider()); Client c1 = api.getClient("client1"); Client c2 = api.getClient("client2"); diff --git a/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java b/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java index 600dc7a6..b5e5bedf 100644 --- a/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java +++ b/src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java @@ -12,6 +12,7 @@ import java.util.Map; import java.util.Optional; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.Test; import dev.openfeature.sdk.fixtures.HookFixtures; @@ -77,7 +78,7 @@ class DeveloperExperienceTest implements HookFixtures { @Test void brokenProvider() { OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new AlwaysBrokenProvider()); + FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider()); Client client = api.getClient(); FlagEvaluationDetails retval = client.getBooleanDetails(flagKey, false); assertEquals(ErrorCode.FLAG_NOT_FOUND, retval.getErrorCode()); @@ -87,14 +88,14 @@ class DeveloperExperienceTest implements HookFixtures { } @Test - void providerLockedPerTransaction() throws InterruptedException { + void providerLockedPerTransaction() { class MutatingHook implements Hook { @Override // change the provider during a before hook - this should not impact the evaluation in progress public Optional before(HookContext ctx, Map hints) { - OpenFeatureAPI.getInstance().setProvider(new NoOpProvider()); + FeatureProviderTestUtils.setFeatureProvider(new NoOpProvider()); return Optional.empty(); } } @@ -102,7 +103,7 @@ public Optional before(HookContext ctx, Map hints) { final String defaultValue = "string-value"; final OpenFeatureAPI api = OpenFeatureAPI.getInstance(); final Client client = api.getClient(); - api.setProvider(new DoSomethingProvider()); + FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider()); api.addHooks(new MutatingHook()); // if provider is changed during an evaluation transaction it should proceed with the original provider diff --git a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java index e246c6d6..e508bdd0 100644 --- a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java @@ -1,7 +1,6 @@ package dev.openfeature.sdk; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.InstanceOfAssertFactories.optional; +import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -12,14 +11,12 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import java.io.Serializable; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import dev.openfeature.sdk.exceptions.FlagNotFoundError; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -33,15 +30,19 @@ class FlagEvaluationSpecTest implements HookFixtures { private Logger logger; + private OpenFeatureAPI api; private Client _client() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new NoOpProvider()); + FeatureProviderTestUtils.setFeatureProvider(new NoOpProvider()); return api.getClient(); } + @BeforeEach + void getApiInstance() { + api = OpenFeatureAPI.getInstance(); + } + @AfterEach void reset_ctx() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); api.setEvaluationContext(null); } @@ -61,24 +62,21 @@ private Client _client() { @Specification(number="1.1.2", text="The API MUST provide a function to set the global provider singleton, which accepts an API-conformant provider implementation.") @Test void provider() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); FeatureProvider mockProvider = mock(FeatureProvider.class); - api.setProvider(mockProvider); - assertEquals(mockProvider, api.getProvider()); + FeatureProviderTestUtils.setFeatureProvider(mockProvider); + assertThat(api.getProvider()).isEqualTo(mockProvider); } @Specification(number="1.1.4", text="The API MUST provide a function for retrieving the metadata field of the configured provider.") @Test void provider_metadata() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new DoSomethingProvider()); - assertEquals(DoSomethingProvider.name, api.getProviderMetadata().getName()); + FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider()); + assertThat(api.getProviderMetadata().getName()).isEqualTo(DoSomethingProvider.name); } @Specification(number="1.1.3", text="The API MUST provide a function to add hooks which accepts one or more API-conformant hooks, and appends them to the collection of any previously added hooks. When new hooks are added, previously added hooks are not removed.") @Test void hook_addition() { Hook h1 = mock(Hook.class); Hook h2 = mock(Hook.class); - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); api.addHooks(h1); assertEquals(1, api.getHooks().size()); @@ -91,8 +89,7 @@ private Client _client() { @Specification(number="1.1.5", text="The API MUST provide a function for creating a client which accepts the following options: - name (optional): A logical string identifier for the client.") @Test void namedClient() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - Client c = api.getClient("Sir Calls-a-lot"); + assertThatCode(() -> api.getClient("Sir Calls-a-lot")).doesNotThrowAnyException(); // TODO: Doesn't say that you can *get* the client name.. which seems useful? } @@ -112,8 +109,8 @@ private Client _client() { @Specification(number="1.3.1", text="The client MUST provide methods for typed flag evaluation, including boolean, numeric, string, and structure, with parameters flag key (string, required), default value (boolean | number | string | structure, required), evaluation context (optional), and evaluation options (optional), which returns the flag value.") @Specification(number="1.3.2.1", text="The client SHOULD provide functions for floating-point numbers and integers, consistent with language idioms.") @Test void value_flags() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new DoSomethingProvider()); + FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider()); + Client c = api.getClient(); String key = "key"; @@ -145,8 +142,7 @@ private Client _client() { @Specification(number="1.4.5", text="In cases of normal execution, the evaluation details structure's variant field MUST contain the value of the variant field in the flag resolution structure returned by the configured provider, if the field is set.") @Specification(number="1.4.6", text="In cases of normal execution, the evaluation details structure's reason field MUST contain the value of the reason field in the flag resolution structure returned by the configured provider, if the field is set.") @Test void detail_flags() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new DoSomethingProvider()); + FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider()); Client c = api.getClient(); String key = "key"; @@ -204,8 +200,7 @@ private Client _client() { @Specification(number="1.4.7", text="In cases of abnormal execution, the `evaluation details` structure's `error code` field **MUST** contain an `error code`.") @Specification(number="1.4.12", text="In cases of abnormal execution, the `evaluation details` structure's `error message` field **MAY** contain a string containing additional details about the nature of the error.") @Test void broken_provider() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new AlwaysBrokenProvider()); + FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider()); Client c = api.getClient(); assertFalse(c.getBooleanValue("key", false)); FlagEvaluationDetails details = c.getBooleanDetails("key", false); @@ -215,8 +210,7 @@ private Client _client() { @Specification(number="1.4.10", text="In the case of abnormal execution, the client SHOULD log an informative error message.") @Test void log_on_error() throws NotImplementedException { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new AlwaysBrokenProvider()); + FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider()); Client c = api.getClient(); FlagEvaluationDetails result = c.getBooleanDetails("test", false); @@ -232,16 +226,14 @@ private Client _client() { Client c = _client(); assertNull(c.getMetadata().getName()); - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new AlwaysBrokenProvider()); + FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider()); Client c2 = api.getClient("test"); assertEquals("test", c2.getMetadata().getName()); } @Specification(number="1.4.8", text="In cases of abnormal execution (network failure, unhandled error, etc) the reason field in the evaluation details SHOULD indicate an error.") @Test void reason_is_error_when_there_are_errors() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(new AlwaysBrokenProvider()); + FeatureProviderTestUtils.setFeatureProvider(new AlwaysBrokenProvider()); Client c = api.getClient(); FlagEvaluationDetails result = c.getBooleanDetails("test", false); assertEquals(Reason.ERROR.toString(), result.getReason()); @@ -250,9 +242,8 @@ private Client _client() { @Specification(number="3.2.1", text="The API, Client and invocation MUST have a method for supplying evaluation context.") @Specification(number="3.2.2", text="Evaluation context MUST be merged in the order: API (global; lowest precedence) - client - invocation - before hooks (highest precedence), with duplicate values being overwritten.") @Test void multi_layer_context_merges_correctly() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); DoSomethingProvider provider = new DoSomethingProvider(); - api.setProvider(provider); + FeatureProviderTestUtils.setFeatureProvider(provider); Map attributes = new HashMap<>(); attributes.put("common", new Value("1")); diff --git a/src/test/java/dev/openfeature/sdk/HookSpecTest.java b/src/test/java/dev/openfeature/sdk/HookSpecTest.java index 26a1b49e..d1daa705 100644 --- a/src/test/java/dev/openfeature/sdk/HookSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/HookSpecTest.java @@ -21,7 +21,7 @@ import java.util.Map; import java.util.Optional; -import io.cucumber.java.hu.Ha; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -30,7 +30,7 @@ import dev.openfeature.sdk.fixtures.HookFixtures; import lombok.SneakyThrows; -public class HookSpecTest implements HookFixtures { +class HookSpecTest implements HookFixtures { @AfterEach void emptyApiHooks() { // it's a singleton. Don't pollute each test. @@ -390,7 +390,7 @@ public void finallyAfter(HookContext ctx, Map hints) { InOrder order = inOrder(hook, provider); OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(provider); + FeatureProviderTestUtils.setFeatureProvider(provider); Client client = api.getClient(); client.getBooleanValue("key", false, new ImmutableContext(), FlagEvaluationOptions.builder().hook(hook).build()); @@ -493,7 +493,7 @@ public void finallyAfter(HookContext ctx, Map hints) { .build()); OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(provider); + FeatureProviderTestUtils.setFeatureProvider(provider); Client client = api.getClient(); client.getBooleanValue("key", false, invocationCtx, FlagEvaluationOptions.builder() @@ -551,12 +551,11 @@ public void finallyAfter(HookContext ctx, Map hints) { private Client getClient(FeatureProvider provider) { OpenFeatureAPI api = OpenFeatureAPI.getInstance(); if (provider == null) { - api.setProvider(new NoOpProvider()); + FeatureProviderTestUtils.setFeatureProvider(new NoOpProvider()); } else { - api.setProvider(provider); + FeatureProviderTestUtils.setFeatureProvider(provider); } - Client client = api.getClient(); - return client; + return api.getClient(); } @Specification(number="4.3.1", text="Hooks MUST specify at least one stage.") @@ -565,14 +564,12 @@ private Client getClient(FeatureProvider provider) { @Specification(number="4.3.8.1", text="Instead of finally, finallyAfter SHOULD be used.") @SneakyThrows @Test void doesnt_use_finally() { - try { - Hook.class.getMethod("finally", HookContext.class, Map.class); - fail("Not possible. Finally is a reserved word."); - } catch (NoSuchMethodException e) { - // expected - } + assertThatCode(() -> Hook.class.getMethod("finally", HookContext.class, Map.class)) + .as("Not possible. Finally is a reserved word.") + .isInstanceOf(NoSuchMethodException.class); - Hook.class.getMethod("finallyAfter", HookContext.class, Map.class); + assertThatCode(() -> Hook.class.getMethod("finallyAfter", HookContext.class, Map.class)) + .doesNotThrowAnyException(); } } diff --git a/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java new file mode 100644 index 00000000..7061719f --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java @@ -0,0 +1,81 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.testutils.exception.TestException; +import org.junit.jupiter.api.*; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.Mockito.*; + +class InitializeBehaviorSpecTest { + + @BeforeEach + void setupTest() { + OpenFeatureAPI.getInstance().setProvider(new NoOpProvider()); + } + + @Nested + class DefaultProvider { + + @Specification(number = "1.1.2.2", text = "The `provider mutator` function MUST invoke the `initialize` " + + "function on the newly registered provider before using it to resolve flag values.") + @Test + @DisplayName("must call initialize function of the newly registered provider before using it for " + + "flag evaluation") + void mustCallInitializeFunctionOfTheNewlyRegisteredProviderBeforeUsingItForFlagEvaluation() { + FeatureProvider featureProvider = mock(FeatureProvider.class); + + OpenFeatureAPI.getInstance().setProvider(featureProvider); + + verify(featureProvider, timeout(1000)).initialize(); + } + + @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " + + "exceptions, or otherwise abnormally terminate. Flag evaluation calls must always return the " + + "`default value` in the event of abnormal execution. Exceptions include functions or methods for " + + "the purposes for configuration or setup.") + @Test + @DisplayName("should catch exception thrown by the provider on initialization") + void shouldCatchExceptionThrownByTheProviderOnInitialization() { + FeatureProvider featureProvider = mock(FeatureProvider.class); + doThrow(TestException.class).when(featureProvider).initialize(); + + assertThatCode(() -> OpenFeatureAPI.getInstance().setProvider(featureProvider)) + .doesNotThrowAnyException(); + + verify(featureProvider, timeout(1000)).initialize(); + } + } + + @Nested + class ProviderForNamedClient { + + @Specification(number = "1.1.2.2", text = "The `provider mutator` function MUST invoke the `initialize`" + + " function on the newly registered provider before using it to resolve flag values.") + @Test + @DisplayName("must call initialize function of the newly registered named provider before using it " + + "for flag evaluation") + void mustCallInitializeFunctionOfTheNewlyRegisteredNamedProviderBeforeUsingItForFlagEvaluation() { + FeatureProvider featureProvider = mock(FeatureProvider.class); + + OpenFeatureAPI.getInstance().setProvider("clientName", featureProvider); + + verify(featureProvider, timeout(1000)).initialize(); + } + + @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " + + "exceptions, or otherwise abnormally terminate. Flag evaluation calls must always return the " + + "`default value` in the event of abnormal execution. Exceptions include functions or methods for " + + "the purposes for configuration or setup.") + @Test + @DisplayName("should catch exception thrown by the named client provider on initialization") + void shouldCatchExceptionThrownByTheNamedClientProviderOnInitialization() { + FeatureProvider featureProvider = mock(FeatureProvider.class); + doThrow(TestException.class).when(featureProvider).initialize(); + + assertThatCode(() -> OpenFeatureAPI.getInstance().setProvider("clientName", featureProvider)) + .doesNotThrowAnyException(); + + verify(featureProvider, timeout(1000)).initialize(); + } + } +} diff --git a/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java b/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java index 4428f9ff..a49bf643 100644 --- a/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java +++ b/src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java @@ -1,26 +1,39 @@ package dev.openfeature.sdk; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +class OpenFeatureAPITest { + + private static final String CLIENT_NAME = "client name"; + + private OpenFeatureAPI api; + + @BeforeEach + void setupTest() { + api = OpenFeatureAPI.getInstance(); + } -public class OpenFeatureAPITest { @Test void namedProviderTest() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); FeatureProvider provider = new NoOpProvider(); - api.setProvider("namedProviderTest", provider); - assertEquals(provider.getMetadata().getName(), api.getProviderMetadata("namedProviderTest").getName()); + FeatureProviderTestUtils.setFeatureProvider("namedProviderTest", provider); + + assertThat(provider.getMetadata().getName()) + .isEqualTo(api.getProviderMetadata("namedProviderTest").getName()); } - @Test void settingDefaultProviderToNullErrors() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - assertThrows(IllegalArgumentException.class, () -> api.setProvider(null)); + @Test + void settingDefaultProviderToNullErrors() { + assertThatCode(() -> api.setProvider(null)).isInstanceOf(IllegalArgumentException.class); } - @Test void settingNamedClientProviderToNullErrors() { - OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - assertThrows(IllegalArgumentException.class, () -> api.setProvider("client-name", null)); + @Test + void settingNamedClientProviderToNullErrors() { + assertThatCode(() -> api.setProvider(CLIENT_NAME, null)).isInstanceOf(IllegalArgumentException.class); } } diff --git a/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java b/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java new file mode 100644 index 00000000..00c7949e --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java @@ -0,0 +1,425 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.testutils.exception.TestException; +import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.function.Function; + +import static dev.openfeature.sdk.fixtures.ProviderFixture.*; +import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doBlock; +import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doDelayResponse; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +class ProviderRepositoryTest { + + private static final String CLIENT_NAME = "client name"; + private static final String ANOTHER_CLIENT_NAME = "another client name"; + private static final String FEATURE_KEY = "some key"; + + private final ExecutorService executorService = Executors.newCachedThreadPool(); + + private ProviderRepository providerRepository; + + @BeforeEach + void setupTest() { + providerRepository = new ProviderRepository(); + } + + @Nested + class InitializationBehavior { + + @Nested + class DefaultProvider { + + @Test + @DisplayName("should reject null as default provider") + void shouldRejectNullAsDefaultProvider() { + assertThatCode(() -> providerRepository.setProvider(null)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("should have NoOpProvider set as default on initialization") + void shouldHaveNoOpProviderSetAsDefaultOnInitialization() { + assertThat(providerRepository.getProvider()).isInstanceOf(NoOpProvider.class); + } + + @Test + @DisplayName("should immediately return when calling the provider mutator") + void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + FeatureProvider featureProvider = createMockedProvider(); + doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(); + + await() + .alias("wait for provider mutator to return") + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(() -> { + providerRepository.setProvider(featureProvider); + verify(featureProvider, timeout(100)).initialize(); + return true; + }); + + verify(featureProvider).initialize(); + } + + @Test + @DisplayName("should not return set provider if initialize has not yet been finished executing") + void shouldNotReturnSetProviderIfItsInitializeMethodHasNotYetBeenFinishedExecuting() { + CountDownLatch latch = new CountDownLatch(1); + FeatureProvider newProvider = createMockedProvider(); + doBlock(latch).when(newProvider).initialize(); + FeatureProvider oldProvider = providerRepository.getProvider(); + + providerRepository.setProvider(newProvider); + + FeatureProvider providerWhileInitialization = providerRepository.getProvider(); + latch.countDown(); + + assertThat(providerWhileInitialization).isEqualTo(oldProvider); + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> assertThat(providerRepository.getProvider()).isEqualTo(newProvider)); + verify(newProvider, timeout(100)).initialize(); + } + + @SneakyThrows + @Test + @DisplayName("should discard provider still initializing if a newer has finished before") + void shouldDiscardProviderStillInitializingIfANewerHasFinishedBefore() { + CountDownLatch latch = new CountDownLatch(1); + CountDownLatch testBlockingLatch = new CountDownLatch(1); + FeatureProvider blockedProvider = createBlockedProvider(latch, testBlockingLatch::countDown); + FeatureProvider fastProvider = createUnblockingProvider(latch); + + providerRepository.setProvider(blockedProvider); + providerRepository.setProvider(fastProvider); + + assertThat(testBlockingLatch.await(2, SECONDS)) + .as("blocking provider initialization not completed within 2 seconds") + .isTrue(); + + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> assertThat(providerRepository.getProvider()).isEqualTo(fastProvider)); + + verify(blockedProvider, timeout(100)).initialize(); + verify(fastProvider, timeout(100)).initialize(); + } + + @Test + @DisplayName("should avoid additional initialization call if provider has been initialized already") + void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() { + FeatureProvider provider = createMockedProvider(); + setFeatureProvider(CLIENT_NAME, provider); + + setFeatureProvider(provider); + + verify(provider).initialize(); + } + } + + @Nested + class NamedProvider { + + @Test + @DisplayName("should reject null as named provider") + void shouldRejectNullAsNamedProvider() { + assertThatCode(() -> providerRepository.setProvider(CLIENT_NAME, null)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("should reject null as client name") + void shouldRejectNullAsDefaultProvider() { + NoOpProvider provider = new NoOpProvider(); + assertThatCode(() -> providerRepository.setProvider(null, provider)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("should immediately return when calling the named client provider mutator") + void shouldImmediatelyReturnWhenCallingTheNamedClientProviderMutator() { + FeatureProvider featureProvider = createMockedProvider(); + doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(); + + await() + .alias("wait for provider mutator to return") + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(() -> { + providerRepository.setProvider("named client", featureProvider); + verify(featureProvider, timeout(1000)).initialize(); + return true; + }); + } + + @Test + @DisplayName("should not return set provider if it's initialization has not yet been finished executing") + void shouldNotReturnSetProviderIfItsInitializeMethodHasNotYetBeenFinishedExecuting() { + CountDownLatch latch = new CountDownLatch(1); + FeatureProvider newProvider = createMockedProvider(); + doBlock(latch).when(newProvider).initialize(); + FeatureProvider oldProvider = createMockedProvider(); + setFeatureProvider(CLIENT_NAME, oldProvider); + + providerRepository.setProvider(CLIENT_NAME, newProvider); + FeatureProvider providerWhileInitialization = getNamedProvider(); + latch.countDown(); + + assertThat(providerWhileInitialization).isEqualTo(oldProvider); + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> assertThat(getNamedProvider()).isEqualTo(newProvider)); + verify(newProvider, timeout(100)).initialize(); + } + + @SneakyThrows + @Test + @DisplayName("should discard provider still initializing if a newer has finished before") + void shouldDiscardProviderStillInitializingIfANewerHasFinishedBefore() { + String clientName = "clientName"; + CountDownLatch latch = new CountDownLatch(1); + CountDownLatch testBlockingLatch = new CountDownLatch(1); + FeatureProvider blockedProvider = createBlockedProvider(latch, testBlockingLatch::countDown); + FeatureProvider unblockingProvider = createUnblockingProvider(latch); + + providerRepository.setProvider(clientName, blockedProvider); + providerRepository.setProvider(clientName, unblockingProvider); + + assertThat(testBlockingLatch.await(2, SECONDS)) + .as("blocking provider initialization not completed within 2 seconds") + .isTrue(); + + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> assertThat(providerRepository.getProvider(clientName)) + .isEqualTo(unblockingProvider)); + + verify(blockedProvider, timeout(100)).initialize(); + verify(unblockingProvider, timeout(100)).initialize(); + } + + @Test + @DisplayName("should avoid additional initialization call if provider has been initialized already") + void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() { + FeatureProvider provider = createMockedProvider(); + setFeatureProvider(provider); + + setFeatureProvider(CLIENT_NAME, provider); + + verify(provider).initialize(); + } + } + } + + @Nested + class ShutdownBehavior { + + @Nested + class DefaultProvider { + + @Test + @DisplayName("should immediately return when calling the provider mutator") + void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + FeatureProvider newProvider = createMockedProvider(); + doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(); + + await() + .alias("wait for provider mutator to return") + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(() -> { + providerRepository.setProvider(newProvider); + verify(newProvider, timeout(100)).initialize(); + return true; + }); + + verify(newProvider).initialize(); + } + + @Test + @DisplayName("should use old provider if replacing one has not yet been finished initializing") + void shouldUseOldProviderIfReplacingOneHasNotYetBeenFinishedInitializing() { + CountDownLatch latch = new CountDownLatch(1); + FeatureProvider newProvider = createMockedProvider(); + doBlock(latch).when(newProvider).initialize(); + FeatureProvider oldProvider = createMockedProvider(); + + setFeatureProvider(oldProvider); + providerRepository.setProvider(newProvider); + + providerRepository.getProvider().getBooleanEvaluation("some key", true, null); + latch.countDown(); + + await() + .atMost(Duration.ofSeconds(1)) + .pollDelay(Duration.ofMillis(1)) + .untilAsserted(() -> assertThat(getProvider()).isEqualTo(newProvider)); + verify(oldProvider, timeout(100)).getBooleanEvaluation(any(), any(), any()); + verify(newProvider, never()).getBooleanEvaluation(any(), any(), any()); + } + + @Test + @DisplayName("should not call shutdown if replaced default provider is bound as named provider") + void shouldNotCallShutdownIfReplacedDefaultProviderIsBoundAsNamedProvider() { + FeatureProvider oldProvider = createMockedProvider(); + FeatureProvider newProvider = createMockedProvider(); + setFeatureProvider(oldProvider); + setFeatureProvider(CLIENT_NAME, oldProvider); + + setFeatureProvider(newProvider); + + verify(oldProvider, never()).shutdown(); + } + } + + @Nested + class NamedProvider { + + @Test + @DisplayName("should immediately return when calling the provider mutator") + void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + FeatureProvider newProvider = createMockedProvider(); + doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(); + + Future providerMutation = executorService + .submit(() -> providerRepository.setProvider(CLIENT_NAME, newProvider)); + + await() + .alias("wait for provider mutator to return") + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(providerMutation::isDone); + } + + @Test + @DisplayName("should use old provider if replacement one has not yet been finished initializing") + void shouldUseOldProviderIfReplacementHasNotYetBeenFinishedInitializing() { + CountDownLatch latch = new CountDownLatch(1); + FeatureProvider newProvider = createMockedProvider(); + doBlock(latch).when(newProvider).initialize(); + FeatureProvider oldProvider = createMockedProvider(); + + setFeatureProvider(CLIENT_NAME, oldProvider); + providerRepository.setProvider(CLIENT_NAME, newProvider); + + providerRepository.getProvider(CLIENT_NAME).getBooleanEvaluation(FEATURE_KEY, true, null); + latch.countDown(); + + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> assertThat(getNamedProvider()).isEqualTo(newProvider)); + verify(oldProvider, timeout(100)).getBooleanEvaluation(eq(FEATURE_KEY), any(), any()); + verify(newProvider, never()).getBooleanEvaluation(any(), any(), any()); + } + + @Test + @DisplayName("should not call shutdown if replaced provider is bound to multiple names") + void shouldNotCallShutdownIfReplacedProviderIsBoundToMultipleNames() { + FeatureProvider oldProvider = createMockedProvider(); + FeatureProvider newProvider = createMockedProvider(); + setFeatureProvider(CLIENT_NAME, oldProvider); + setFeatureProvider(ANOTHER_CLIENT_NAME, oldProvider); + + setFeatureProvider(CLIENT_NAME, newProvider); + + verify(oldProvider, never()).shutdown(); + } + + @Test + @DisplayName("should not call shutdown if replaced provider is bound as default provider") + void shouldNotCallShutdownIfReplacedProviderIsBoundAsDefaultProvider() { + FeatureProvider oldProvider = createMockedProvider(); + FeatureProvider newProvider = createMockedProvider(); + setFeatureProvider(oldProvider); + setFeatureProvider(CLIENT_NAME, oldProvider); + + setFeatureProvider(CLIENT_NAME, newProvider); + + verify(oldProvider, never()).shutdown(); + } + + @Test + @DisplayName("should not throw exception if provider throws one on shutdown") + void shouldNotThrowExceptionIfProviderThrowsOneOnShutdown() { + FeatureProvider provider = createMockedProvider(); + doThrow(TestException.class).when(provider).shutdown(); + setFeatureProvider(provider); + + assertThatCode(() -> setFeatureProvider(new NoOpProvider())).doesNotThrowAnyException(); + + verify(provider).shutdown(); + } + } + } + + @Test + @DisplayName("should shutdown all feature providers on shutdown") + void shouldShutdownAllFeatureProvidersOnShutdown() { + FeatureProvider featureProvider1 = createMockedProvider(); + FeatureProvider featureProvider2 = createMockedProvider(); + + setFeatureProvider(featureProvider1); + setFeatureProvider(CLIENT_NAME, featureProvider1); + setFeatureProvider(ANOTHER_CLIENT_NAME, featureProvider2); + + providerRepository.shutdown(); + + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> { + assertThat(providerRepository.getProvider()).isInstanceOf(NoOpProvider.class); + assertThat(providerRepository.getProvider(CLIENT_NAME)).isInstanceOf(NoOpProvider.class); + assertThat(providerRepository.getProvider(ANOTHER_CLIENT_NAME)).isInstanceOf(NoOpProvider.class); + }); + verify(featureProvider1).shutdown(); + verify(featureProvider2).shutdown(); + } + + private FeatureProvider getProvider() { + return providerRepository.getProvider(); + } + + private FeatureProvider getNamedProvider() { + return providerRepository.getProvider(CLIENT_NAME); + } + + private void setFeatureProvider(FeatureProvider provider) { + providerRepository.setProvider(provider); + waitForSettingProviderHasBeenCompleted(ProviderRepository::getProvider, provider); + } + + private void setFeatureProvider(String namedProvider, FeatureProvider provider) { + providerRepository.setProvider(namedProvider, provider); + waitForSettingProviderHasBeenCompleted(repository -> repository.getProvider(namedProvider), provider); + } + + private void waitForSettingProviderHasBeenCompleted( + Function extractor, + FeatureProvider provider) { + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(() -> extractor.apply(providerRepository) == provider); + } + +} diff --git a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java new file mode 100644 index 00000000..d191c8c4 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java @@ -0,0 +1,117 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.fixtures.ProviderFixture; +import dev.openfeature.sdk.testutils.exception.TestException; +import org.awaitility.Awaitility; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.Duration; + +import static dev.openfeature.sdk.testutils.FeatureProviderTestUtils.setFeatureProvider; +import static org.mockito.Mockito.*; + +class ShutdownBehaviorSpecTest { + + @BeforeEach + void resetFeatureProvider() { + setFeatureProvider(new NoOpProvider()); + } + + @Nested + class DefaultProvider { + + @Specification(number = "1.1.2.3", text = "The `provider mutator` function MUST invoke the `shutdown` function on the previously registered provider once it's no longer being used to resolve flag values.") + @Test + @DisplayName("must invoke shutdown method on previously registered provider once it should not be used for flag evaluation anymore") + void mustInvokeShutdownMethodOnPreviouslyRegisteredProviderOnceItShouldNotBeUsedForFlagEvaluationAnymore() { + FeatureProvider featureProvider = ProviderFixture.createMockedProvider(); + + setFeatureProvider(featureProvider); + setFeatureProvider(new NoOpProvider()); + + verify(featureProvider, timeout(1000)).shutdown(); + } + + @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " + + "exceptions, or otherwise abnormally terminate. Flag evaluation calls must always return the " + + "`default value` in the event of abnormal execution. Exceptions include functions or methods for " + + "the purposes for configuration or setup.") + @Test + @DisplayName("should catch exception thrown by the provider on shutdown") + void shouldCatchExceptionThrownByTheProviderOnShutdown() { + FeatureProvider featureProvider = ProviderFixture.createMockedProvider(); + doThrow(TestException.class).when(featureProvider).shutdown(); + + setFeatureProvider(featureProvider); + setFeatureProvider(new NoOpProvider()); + + verify(featureProvider, timeout(1000)).shutdown(); + } + } + + @Nested + class NamedProvider { + + @Specification(number = "1.1.2.3", text = "The `provider mutator` function MUST invoke the `shutdown` function on the previously registered provider once it's no longer being used to resolve flag values.") + @Test + @DisplayName("must invoke shutdown method on previously registered provider once it should not be used for flag evaluation anymore") + void mustInvokeShutdownMethodOnPreviouslyRegisteredProviderOnceItShouldNotBeUsedForFlagEvaluationAnymore() { + String clientName = "clientName"; + FeatureProvider featureProvider = ProviderFixture.createMockedProvider(); + + setFeatureProvider(clientName, featureProvider); + setFeatureProvider(clientName, new NoOpProvider()); + + verify(featureProvider, timeout(1000)).shutdown(); + } + + @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " + + "exceptions, or otherwise abnormally terminate. Flag evaluation calls must always return the " + + "`default value` in the event of abnormal execution. Exceptions include functions or methods for " + + "the purposes for configuration or setup.") + @Test + @DisplayName("should catch exception thrown by the named client provider on shutdown") + void shouldCatchExceptionThrownByTheNamedClientProviderOnShutdown() { + String clientName = "clientName"; + FeatureProvider featureProvider = ProviderFixture.createMockedProvider(); + doThrow(TestException.class).when(featureProvider).shutdown(); + + setFeatureProvider(clientName, featureProvider); + setFeatureProvider(clientName, new NoOpProvider()); + + verify(featureProvider, timeout(1000)).shutdown(); + } + } + + @Nested + class General { + + @Specification(number = "1.6.1", text = "The API MUST define a shutdown function which, when called, must call the respective shutdown function on the active provider.") + @Test + @DisplayName("must shutdown all providers on shutting down api") + void mustShutdownAllProvidersOnShuttingDownApi() { + FeatureProvider defaultProvider = ProviderFixture.createMockedProvider(); + FeatureProvider namedProvider = ProviderFixture.createMockedProvider(); + setFeatureProvider(defaultProvider); + setFeatureProvider("clientName", namedProvider); + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); + + synchronized (OpenFeatureAPI.class) { + api.shutdown(); + + Awaitility + .await() + .atMost(Duration.ofSeconds(1)) + .untilAsserted(() -> { + verify(defaultProvider).shutdown(); + verify(namedProvider).shutdown(); + }); + + api.resetProviderRepository(); + } + } + } +} diff --git a/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java b/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java new file mode 100644 index 00000000..f0b78642 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java @@ -0,0 +1,43 @@ +package dev.openfeature.sdk.fixtures; + +import dev.openfeature.sdk.FeatureProvider; +import lombok.experimental.UtilityClass; +import org.mockito.stubbing.Answer; + +import java.util.concurrent.CountDownLatch; + +import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doBlock; +import static org.mockito.Mockito.*; + +@UtilityClass +public class ProviderFixture { + + public static FeatureProvider createMockedProvider() { + return mock(FeatureProvider.class); + } + + public static FeatureProvider createBlockedProvider(CountDownLatch latch, Runnable onAnswer) { + FeatureProvider provider = createMockedProvider(); + doBlock(latch, createAnswerExecutingCode(onAnswer)).when(provider).initialize(); + doReturn("blockedProvider").when(provider).toString(); + return provider; + } + + private static Answer createAnswerExecutingCode(Runnable onAnswer) { + return invocation -> { + onAnswer.run(); + return null; + }; + } + + public static FeatureProvider createUnblockingProvider(CountDownLatch latch) { + FeatureProvider provider = createMockedProvider(); + doAnswer(invocation -> { + latch.countDown(); + return null; + }).when(provider).initialize(); + doReturn("unblockingProvider").when(provider).toString(); + return provider; + } + +} diff --git a/src/test/java/dev/openfeature/sdk/testutils/FeatureProviderTestUtils.java b/src/test/java/dev/openfeature/sdk/testutils/FeatureProviderTestUtils.java new file mode 100644 index 00000000..5f8c13db --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/testutils/FeatureProviderTestUtils.java @@ -0,0 +1,30 @@ +package dev.openfeature.sdk.testutils; + +import java.time.Duration; +import java.util.function.Function; + +import dev.openfeature.sdk.*; +import lombok.experimental.UtilityClass; + +import static org.awaitility.Awaitility.await; + +@UtilityClass +public class FeatureProviderTestUtils { + + public static void setFeatureProvider(FeatureProvider provider) { + OpenFeatureAPI.getInstance().setProvider(provider); + waitForProviderInitializationComplete(OpenFeatureAPI::getProvider, provider); + } + + private static void waitForProviderInitializationComplete(Function extractor, FeatureProvider provider) { + await() + .pollDelay(Duration.ofMillis(1)) + .atMost(Duration.ofSeconds(1)) + .until(() -> extractor.apply(OpenFeatureAPI.getInstance()) == provider); + } + + public static void setFeatureProvider(String namedProvider, FeatureProvider provider) { + OpenFeatureAPI.getInstance().setProvider(namedProvider, provider); + waitForProviderInitializationComplete(api -> api.getProvider(namedProvider), provider); + } +} diff --git a/src/test/java/dev/openfeature/sdk/testutils/exception/TestException.java b/src/test/java/dev/openfeature/sdk/testutils/exception/TestException.java new file mode 100644 index 00000000..c6918b02 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/testutils/exception/TestException.java @@ -0,0 +1,9 @@ +package dev.openfeature.sdk.testutils.exception; + +public class TestException extends RuntimeException { + + @Override + public String getMessage() { + return "don't panic, it's just a test"; + } +} diff --git a/src/test/java/dev/openfeature/sdk/testutils/stubbing/ConditionStubber.java b/src/test/java/dev/openfeature/sdk/testutils/stubbing/ConditionStubber.java new file mode 100644 index 00000000..11cf2649 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/testutils/stubbing/ConditionStubber.java @@ -0,0 +1,37 @@ +package dev.openfeature.sdk.testutils.stubbing; + +import java.time.Duration; +import java.util.concurrent.CountDownLatch; + +import lombok.experimental.UtilityClass; +import org.mockito.stubbing.*; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.mockito.Mockito.doAnswer; + +@UtilityClass +public class ConditionStubber { + + @SuppressWarnings("java:S2925") + public static Stubber doDelayResponse(Duration duration) { + return doAnswer(invocation -> { + MILLISECONDS.sleep(duration.toMillis()); + return null; + }); + } + + public static Stubber doBlock(CountDownLatch latch) { + return doAnswer(invocation -> { + latch.await(); + return null; + }); + } + + public static Stubber doBlock(CountDownLatch latch, Answer answer) { + return doAnswer(invocation -> { + latch.await(); + return answer.answer(invocation); + }); + } + +} From 3ed40a388797dc6939bff5d06e7c4528773df791 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Tue, 6 Jun 2023 18:44:49 -0700 Subject: [PATCH 093/134] feat: add flag metadata (#459) Signed-off-by: Kavindu Dodanduwa --- .../sdk/FlagEvaluationDetails.java | 11 +- .../dev/openfeature/sdk/FlagMetadata.java | 188 ++++++++++++++++++ .../openfeature/sdk/ProviderEvaluation.java | 2 + .../openfeature/sdk/DoSomethingProvider.java | 17 +- .../sdk/FlagEvaluationSpecTest.java | 16 +- .../dev/openfeature/sdk/FlagMetadataTest.java | 53 +++++ 6 files changed, 275 insertions(+), 12 deletions(-) create mode 100644 src/main/java/dev/openfeature/sdk/FlagMetadata.java create mode 100644 src/test/java/dev/openfeature/sdk/FlagMetadataTest.java diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java index 67ee853d..24e6a398 100644 --- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java +++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java @@ -7,23 +7,27 @@ /** * Contains information about how the evaluation happened, including any resolved values. + * * @param the type of the flag being evaluated. */ -@Data @Builder +@Data +@Builder public class FlagEvaluationDetails implements BaseEvaluation { + private String flagKey; private T value; @Nullable private String variant; @Nullable private String reason; private ErrorCode errorCode; @Nullable private String errorMessage; + @Builder.Default private FlagMetadata flagMetadata = FlagMetadata.builder().build(); /** * Generate detail payload from the provider response. * * @param providerEval provider response - * @param flagKey key for the flag being evaluated - * @param type of flag being returned + * @param flagKey key for the flag being evaluated + * @param type of flag being returned * @return detail payload */ public static FlagEvaluationDetails from(ProviderEvaluation providerEval, String flagKey) { @@ -33,6 +37,7 @@ public static FlagEvaluationDetails from(ProviderEvaluation providerEv .variant(providerEval.getVariant()) .reason(providerEval.getReason()) .errorCode(providerEval.getErrorCode()) + .flagMetadata(providerEval.getFlagMetadata()) .build(); } } diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java new file mode 100644 index 00000000..e9b6ccb6 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -0,0 +1,188 @@ +package dev.openfeature.sdk; + +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * Immutable Flag Metadata representation. Implementation is backed by a {@link Map} and immutability is provided + * through builder and accessors. + */ +@Slf4j +public class FlagMetadata { + private final Map metadata; + + private FlagMetadata(Map metadata) { + this.metadata = metadata; + } + + /** + * Retrieve a {@link String} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public String getString(final String key) { + return getValue(key, String.class); + } + + /** + * Retrieve a {@link Integer} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Integer getInteger(final String key) { + return getValue(key, Integer.class); + } + + /** + * Retrieve a {@link Long} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Long getLong(final String key) { + return getValue(key, Long.class); + } + + /** + * Retrieve a {@link Float} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Float getFloat(final String key) { + return getValue(key, Float.class); + } + + /** + * Retrieve a {@link Double} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Double getDouble(final String key) { + return getValue(key, Double.class); + } + + /** + * Retrieve a {@link Boolean} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Boolean getBoolean(final String key) { + return getValue(key, Boolean.class); + } + + private T getValue(final String key, final Class type) { + final Object o = metadata.get(key); + + if (o == null) { + log.debug("Metadata key " + key + "does not exist"); + return null; + } + + try { + return type.cast(o); + } catch (ClassCastException e) { + log.debug("Error retrieving value for key " + key, e); + return null; + } + } + + + /** + * Obtain a builder for {@link FlagMetadata}. + */ + public static FlagMetadataBuilder builder() { + return new FlagMetadataBuilder(); + } + + /** + * Immutable builder for {@link FlagMetadata}. + */ + public static class FlagMetadataBuilder { + private final Map metadata; + + private FlagMetadataBuilder() { + metadata = new HashMap<>(); + } + + /** + * Add String value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addString(final String key, final String value) { + metadata.put(key, value); + return this; + } + + /** + * Add Integer value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addInteger(final String key, final Integer value) { + metadata.put(key, value); + return this; + } + + /** + * Add Long value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addLong(final String key, final Long value) { + metadata.put(key, value); + return this; + } + + /** + * Add Float value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addFloat(final String key, final Float value) { + metadata.put(key, value); + return this; + } + + /** + * Add Double value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addDouble(final String key, final Double value) { + metadata.put(key, value); + return this; + } + + /** + * Add Boolean value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addBoolean(final String key, final Boolean value) { + metadata.put(key, value); + return this; + } + + /** + * Retrieve {@link FlagMetadata} with provided key,value pairs. + */ + public FlagMetadata build() { + return new FlagMetadata(this.metadata); + } + + } +} diff --git a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java index 9ba1ab9a..ffa5c3cc 100644 --- a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java +++ b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java @@ -13,4 +13,6 @@ public class ProviderEvaluation implements BaseEvaluation { @Nullable private String reason; ErrorCode errorCode; @Nullable private String errorMessage; + @Builder.Default + private FlagMetadata flagMetadata = FlagMetadata.builder().build(); } diff --git a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java index d87fa374..26e6737b 100644 --- a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java +++ b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java @@ -1,11 +1,14 @@ package dev.openfeature.sdk; -public class DoSomethingProvider implements FeatureProvider { +class DoSomethingProvider implements FeatureProvider { + + static final String name = "Something"; + // Flag evaluation metadata + static final FlagMetadata flagMetadata = FlagMetadata.builder().build(); - public static final String name = "Something"; private EvaluationContext savedContext; - public EvaluationContext getMergedContext() { + EvaluationContext getMergedContext() { return savedContext; } @@ -18,13 +21,16 @@ public Metadata getMetadata() { public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { savedContext = ctx; return ProviderEvaluation.builder() - .value(!defaultValue).build(); + .value(!defaultValue) + .flagMetadata(flagMetadata) + .build(); } @Override public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) { return ProviderEvaluation.builder() .value(new StringBuilder(defaultValue).reverse().toString()) + .flagMetadata(flagMetadata) .build(); } @@ -33,6 +39,7 @@ public ProviderEvaluation getIntegerEvaluation(String key, Integer defa savedContext = ctx; return ProviderEvaluation.builder() .value(defaultValue * 100) + .flagMetadata(flagMetadata) .build(); } @@ -41,6 +48,7 @@ public ProviderEvaluation getDoubleEvaluation(String key, Double default savedContext = ctx; return ProviderEvaluation.builder() .value(defaultValue * 100) + .flagMetadata(flagMetadata) .build(); } @@ -49,6 +57,7 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa savedContext = invocationContext; return ProviderEvaluation.builder() .value(null) + .flagMetadata(flagMetadata) .build(); } } diff --git a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java index e508bdd0..57f0c045 100644 --- a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java @@ -1,6 +1,8 @@ package dev.openfeature.sdk; -import static org.assertj.core.api.Assertions.*; +import static dev.openfeature.sdk.DoSomethingProvider.flagMetadata; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -15,18 +17,18 @@ import java.util.List; import java.util.Map; -import dev.openfeature.sdk.exceptions.FlagNotFoundError; -import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import dev.openfeature.sdk.fixtures.HookFixtures; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.simplify4u.slf4jmock.LoggerMock; import org.slf4j.Logger; +import dev.openfeature.sdk.exceptions.FlagNotFoundError; +import dev.openfeature.sdk.fixtures.HookFixtures; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; + class FlagEvaluationSpecTest implements HookFixtures { private Logger logger; @@ -150,6 +152,7 @@ void getApiInstance() { .flagKey(key) .value(false) .variant(null) + .flagMetadata(flagMetadata) .build(); assertEquals(bd, c.getBooleanDetails(key, true)); assertEquals(bd, c.getBooleanDetails(key, true, new ImmutableContext())); @@ -159,6 +162,7 @@ void getApiInstance() { .flagKey(key) .value("tset") .variant(null) + .flagMetadata(flagMetadata) .build(); assertEquals(sd, c.getStringDetails(key, "test")); assertEquals(sd, c.getStringDetails(key, "test", new ImmutableContext())); @@ -167,6 +171,7 @@ void getApiInstance() { FlagEvaluationDetails id = FlagEvaluationDetails.builder() .flagKey(key) .value(400) + .flagMetadata(flagMetadata) .build(); assertEquals(id, c.getIntegerDetails(key, 4)); assertEquals(id, c.getIntegerDetails(key, 4, new ImmutableContext())); @@ -175,6 +180,7 @@ void getApiInstance() { FlagEvaluationDetails dd = FlagEvaluationDetails.builder() .flagKey(key) .value(40.0) + .flagMetadata(flagMetadata) .build(); assertEquals(dd, c.getDoubleDetails(key, .4)); assertEquals(dd, c.getDoubleDetails(key, .4, new ImmutableContext())); diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java new file mode 100644 index 00000000..b52eb6de --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -0,0 +1,53 @@ +package dev.openfeature.sdk; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class FlagMetadataTest { + + @Test + @DisplayName("Test metadata payload construction and retrieval") + public void builder_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder() + .addString("string", "string") + .addInteger("integer", 1) + .addLong("long", 1L) + .addFloat("float", 1.5f) + .addDouble("double", Double.MAX_VALUE) + .addBoolean("boolean", Boolean.FALSE) + .build(); + + // then + assertThat(flagMetadata.getString("string")).isEqualTo("string"); + assertThat(flagMetadata.getInteger("integer")).isEqualTo(1); + assertThat(flagMetadata.getLong("long")).isEqualTo(1L); + assertThat(flagMetadata.getFloat("float")).isEqualTo(1.5f); + assertThat(flagMetadata.getDouble("double")).isEqualTo(Double.MAX_VALUE); + assertThat(flagMetadata.getBoolean("boolean")).isEqualTo(Boolean.FALSE); + } + + @Test + @DisplayName("Value type mismatch returns a null") + public void value_type_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder() + .addString("string", "string") + .build(); + + // then + assertThat(flagMetadata.getBoolean("string")).isNull(); + } + + @Test + @DisplayName("A null is returned if key does not exist") + public void notfound_error_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder().build(); + + // then + assertThat(flagMetadata.getBoolean("string")).isNull(); + } +} From 6107e91be4eef92e5dfa96e6b7b862d7e3a85df1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 04:57:26 +0000 Subject: [PATCH 094/134] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.1.2 (#465) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 26cb9329..b98cbc2b 100644 --- a/pom.xml +++ b/pom.xml @@ -257,7 +257,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.0 + 3.1.2 ${surefireArgLine} From 5888aead97a70495b8fd9489aa1a8b23ea2f365e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 06:59:40 -0700 Subject: [PATCH 095/134] chore(deps): update dependency com.google.guava:guava to v32 (#455) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b98cbc2b..a022454b 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ com.google.guava guava - 31.1-jre + 32.0.0-jre test From 56c1bbc8201fc8e312bf4ab208905b53475d3cbd Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Wed, 7 Jun 2023 12:23:18 -0400 Subject: [PATCH 096/134] ci: add codecov token (#466) Setting a Codecov token helps avoid throttling issues. https://github.com/codecov/codecov-action/issues/557#issuecomment-1216749652 Signed-off-by: Michael Beemer --- .github/workflows/merge.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 74a2e9d7..03bd4e59 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -51,6 +51,7 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d with: + token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos flags: unittests # optional name: coverage # optional fail_ci_if_error: true # optional (default = false) From 89cedb9d2ec709d7ad218e8b94852f8b947eb7f6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 13:03:50 +0000 Subject: [PATCH 097/134] chore(deps): update actions/setup-java digest to 87c1c70 (#469) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 03bd4e59..1f1f1289 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 - uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa + uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index f91efa05..fc87e345 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 - uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa + uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9e7739e..79868df2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@ddb82ce8a6ecf5ac3e80c3184839e6661546e4aa + uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 with: java-version: '8' distribution: 'temurin' From 3946211c5d042f17a04d6941430462f70b27a7d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Jun 2023 03:41:13 +0000 Subject: [PATCH 098/134] chore(deps): update dependency com.google.guava:guava to v32.0.1-jre (#470) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a022454b..641d80d0 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ com.google.guava guava - 32.0.0-jre + 32.0.1-jre test From 93dde1d259e86b00db701a753b84ad2c253e21ec Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 9 Jun 2023 07:57:08 -0700 Subject: [PATCH 099/134] chore: expose get value for metadata (#468) expose get value for metadata Signed-off-by: Kavindu Dodanduwa Co-authored-by: Justin Abrahms --- src/main/java/dev/openfeature/sdk/FlagMetadata.java | 5 ++++- .../java/dev/openfeature/sdk/FlagMetadataTest.java | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java index e9b6ccb6..7cd91f8d 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -77,7 +77,10 @@ public Boolean getBoolean(final String key) { return getValue(key, Boolean.class); } - private T getValue(final String key, final Class type) { + /** + * Generic value retrieval for the given key. + */ + public T getValue(final String key, final Class type) { final Object o = metadata.get(key); if (o == null) { diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index b52eb6de..8f96e610 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -22,11 +22,22 @@ public void builder_validation() { // then assertThat(flagMetadata.getString("string")).isEqualTo("string"); + assertThat(flagMetadata.getValue("string", String.class)).isEqualTo("string"); + assertThat(flagMetadata.getInteger("integer")).isEqualTo(1); + assertThat(flagMetadata.getValue("integer", Integer.class)).isEqualTo(1); + assertThat(flagMetadata.getLong("long")).isEqualTo(1L); + assertThat(flagMetadata.getValue("long", Long.class)).isEqualTo(1L); + assertThat(flagMetadata.getFloat("float")).isEqualTo(1.5f); + assertThat(flagMetadata.getValue("float", Float.class)).isEqualTo(1.5f); + assertThat(flagMetadata.getDouble("double")).isEqualTo(Double.MAX_VALUE); + assertThat(flagMetadata.getValue("double", Double.class)).isEqualTo(Double.MAX_VALUE); + assertThat(flagMetadata.getBoolean("boolean")).isEqualTo(Boolean.FALSE); + assertThat(flagMetadata.getValue("boolean", Boolean.class)).isEqualTo(Boolean.FALSE); } @Test @@ -38,7 +49,7 @@ public void value_type_validation() { .build(); // then - assertThat(flagMetadata.getBoolean("string")).isNull(); + assertThat(flagMetadata.getBoolean("string")).isNull(); } @Test From 31f214826453a10d7bef2d1d59033febf75dbb76 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Fri, 9 Jun 2023 08:01:59 -0700 Subject: [PATCH 100/134] chore: seperate release plugins to a profile (#467) seperate deploy plugins to a profile Signed-off-by: Kavindu Dodanduwa Co-authored-by: Justin Abrahms --- pom.xml | 144 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 78 insertions(+), 66 deletions(-) diff --git a/pom.xml b/pom.xml index 641d80d0..f6d637dd 100644 --- a/pom.xml +++ b/pom.xml @@ -178,7 +178,6 @@ - org.codehaus.mojo build-helper-maven-plugin @@ -343,20 +342,6 @@ - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ossrh - https://s01.oss.sonatype.org/ - true - - - - org.apache.maven.plugins maven-jar-plugin @@ -369,56 +354,6 @@ - - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.5.0 - - true - all,-missing - - - - attach-javadocs - - jar - - - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.1.0 - - - sign-artifacts - install - - sign - - - - - org.apache.maven.plugins @@ -496,11 +431,88 @@ -
+ + + deploy + + true + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://s01.oss.sonatype.org/ + true + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.5.0 + + true + all,-missing + + + + attach-javadocs + + jar + + + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.1.0 + + + sign-artifacts + install + + sign + + + + + + + + + + e2e-test From fe420733850018b1d579601a1d3b4149a93605d6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:10:58 +0000 Subject: [PATCH 101/134] chore(deps): update actions/checkout digest to 96f5310 (#471) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static-code-scanning.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 1f1f1289..8474525c 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 + - uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 with: diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index fc87e345..2fe75306 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the code - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 + uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79868df2..2a5dbf27 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: # These steps are only run if this was a merged release-please PR - name: checkout if: ${{ steps.release.outputs.releases_created }} - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 + uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index dfebe829..c92b9308 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@f095bcc56b7c2baf48f3ac70d6d6782f4f553222 + uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL From fa94c0e0ddbcb0bf5e6af7d1b6f53c1b885d7270 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:31:24 +0000 Subject: [PATCH 102/134] chore(deps): update github/codeql-action digest to e287d85 (#472) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 2fe75306..a9ce7041 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/init@e287d85c90597a66e5b4020db41a8b52003a8cb9 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/analyze@e287d85c90597a66e5b4020db41a8b52003a8cb9 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index c92b9308..bbe04710 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/init@e287d85c90597a66e5b4020db41a8b52003a8cb9 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/autobuild@e287d85c90597a66e5b4020db41a8b52003a8cb9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/analyze@e287d85c90597a66e5b4020db41a8b52003a8cb9 From 6d456ca618ba78eadcfe00bd63383b9f7dba32b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 22:50:33 +0000 Subject: [PATCH 103/134] chore(deps): update actions/cache digest to 67b839e (#473) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 8474525c..a3cc3946 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -32,7 +32,7 @@ jobs: server-password: ${{ secrets.OSSRH_PASSWORD }} - name: Cache local Maven repository - uses: actions/cache@04f198bf0b2a39f7230a4304bf07747a0bddf146 + uses: actions/cache@67b839edb68371cc5014f6cea11c9aa77238de78 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index a9ce7041..4db57d12 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -31,7 +31,7 @@ jobs: languages: java - name: Cache local Maven repository - uses: actions/cache@04f198bf0b2a39f7230a4304bf07747a0bddf146 + uses: actions/cache@67b839edb68371cc5014f6cea11c9aa77238de78 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From d309d1633018217e1c2fad8bff8f3b55706aa016 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 00:45:26 +0000 Subject: [PATCH 104/134] chore(deps): update github/codeql-action digest to b8f204c (#474) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4db57d12..45aabd0e 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@e287d85c90597a66e5b4020db41a8b52003a8cb9 + uses: github/codeql-action/init@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e287d85c90597a66e5b4020db41a8b52003a8cb9 + uses: github/codeql-action/analyze@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index bbe04710..1dfc621b 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e287d85c90597a66e5b4020db41a8b52003a8cb9 + uses: github/codeql-action/init@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@e287d85c90597a66e5b4020db41a8b52003a8cb9 + uses: github/codeql-action/autobuild@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e287d85c90597a66e5b4020db41a8b52003a8cb9 + uses: github/codeql-action/analyze@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 From ec6d44ae8969f73098fac8e98830800486b73a9a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 19:21:22 +0000 Subject: [PATCH 105/134] chore(deps): update actions/setup-java digest to 45058d7 (#479) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index a3cc3946..2caa5488 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 + uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 45aabd0e..debf0824 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 + uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a5dbf27..709c7740 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@87c1c7064c0055a1c5bf9f2c9187d414e9764478 + uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 with: java-version: '8' distribution: 'temurin' From 3501425f48feef82a50161ed072a68bae97053c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 22:05:32 +0000 Subject: [PATCH 106/134] chore(deps): update github/codeql-action digest to 0ac1815 (#477) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index debf0824..77f18c54 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 + uses: github/codeql-action/init@0ac18158d140a77edfc969babb80dbc82970eab3 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 + uses: github/codeql-action/analyze@0ac18158d140a77edfc969babb80dbc82970eab3 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 1dfc621b..984527e9 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 + uses: github/codeql-action/init@0ac18158d140a77edfc969babb80dbc82970eab3 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 + uses: github/codeql-action/autobuild@0ac18158d140a77edfc969babb80dbc82970eab3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b8f204c6193e7d80da788437cf3ca4ac0146c2b5 + uses: github/codeql-action/analyze@0ac18158d140a77edfc969babb80dbc82970eab3 From ecfeddf0f67c4d9cf34530f957d139344b622b51 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 16 Jun 2023 13:53:31 -0400 Subject: [PATCH 107/134] chore: rename flag metadata (#478) Signed-off-by: Todd Baert --- .../sdk/FlagEvaluationDetails.java | 2 +- ...agMetadata.java => ImmutableMetadata.java} | 34 +++++++++---------- .../openfeature/sdk/ProviderEvaluation.java | 2 +- .../openfeature/sdk/DoSomethingProvider.java | 2 +- .../dev/openfeature/sdk/FlagMetadataTest.java | 6 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) rename src/main/java/dev/openfeature/sdk/{FlagMetadata.java => ImmutableMetadata.java} (80%) diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java index 24e6a398..0a60565c 100644 --- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java +++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java @@ -20,7 +20,7 @@ public class FlagEvaluationDetails implements BaseEvaluation { @Nullable private String reason; private ErrorCode errorCode; @Nullable private String errorMessage; - @Builder.Default private FlagMetadata flagMetadata = FlagMetadata.builder().build(); + @Builder.Default private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); /** * Generate detail payload from the provider response. diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java similarity index 80% rename from src/main/java/dev/openfeature/sdk/FlagMetadata.java rename to src/main/java/dev/openfeature/sdk/ImmutableMetadata.java index 7cd91f8d..1bc130b4 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java @@ -10,10 +10,10 @@ * through builder and accessors. */ @Slf4j -public class FlagMetadata { +public class ImmutableMetadata { private final Map metadata; - private FlagMetadata(Map metadata) { + private ImmutableMetadata(Map metadata) { this.metadata = metadata; } @@ -98,19 +98,19 @@ public T getValue(final String key, final Class type) { /** - * Obtain a builder for {@link FlagMetadata}. + * Obtain a builder for {@link ImmutableMetadata}. */ - public static FlagMetadataBuilder builder() { - return new FlagMetadataBuilder(); + public static ImmutableMetadataBuilder builder() { + return new ImmutableMetadataBuilder(); } /** - * Immutable builder for {@link FlagMetadata}. + * Immutable builder for {@link ImmutableMetadata}. */ - public static class FlagMetadataBuilder { + public static class ImmutableMetadataBuilder { private final Map metadata; - private FlagMetadataBuilder() { + private ImmutableMetadataBuilder() { metadata = new HashMap<>(); } @@ -120,7 +120,7 @@ private FlagMetadataBuilder() { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addString(final String key, final String value) { + public ImmutableMetadataBuilder addString(final String key, final String value) { metadata.put(key, value); return this; } @@ -131,7 +131,7 @@ public FlagMetadataBuilder addString(final String key, final String value) { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addInteger(final String key, final Integer value) { + public ImmutableMetadataBuilder addInteger(final String key, final Integer value) { metadata.put(key, value); return this; } @@ -142,7 +142,7 @@ public FlagMetadataBuilder addInteger(final String key, final Integer value) { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addLong(final String key, final Long value) { + public ImmutableMetadataBuilder addLong(final String key, final Long value) { metadata.put(key, value); return this; } @@ -153,7 +153,7 @@ public FlagMetadataBuilder addLong(final String key, final Long value) { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addFloat(final String key, final Float value) { + public ImmutableMetadataBuilder addFloat(final String key, final Float value) { metadata.put(key, value); return this; } @@ -164,7 +164,7 @@ public FlagMetadataBuilder addFloat(final String key, final Float value) { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addDouble(final String key, final Double value) { + public ImmutableMetadataBuilder addDouble(final String key, final Double value) { metadata.put(key, value); return this; } @@ -175,16 +175,16 @@ public FlagMetadataBuilder addDouble(final String key, final Double value) { * @param key flag metadata key to add * @param value flag metadata value to add */ - public FlagMetadataBuilder addBoolean(final String key, final Boolean value) { + public ImmutableMetadataBuilder addBoolean(final String key, final Boolean value) { metadata.put(key, value); return this; } /** - * Retrieve {@link FlagMetadata} with provided key,value pairs. + * Retrieve {@link ImmutableMetadata} with provided key,value pairs. */ - public FlagMetadata build() { - return new FlagMetadata(this.metadata); + public ImmutableMetadata build() { + return new ImmutableMetadata(this.metadata); } } diff --git a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java index ffa5c3cc..42441a8e 100644 --- a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java +++ b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java @@ -14,5 +14,5 @@ public class ProviderEvaluation implements BaseEvaluation { ErrorCode errorCode; @Nullable private String errorMessage; @Builder.Default - private FlagMetadata flagMetadata = FlagMetadata.builder().build(); + private ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); } diff --git a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java index 26e6737b..8d1c4514 100644 --- a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java +++ b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java @@ -4,7 +4,7 @@ class DoSomethingProvider implements FeatureProvider { static final String name = "Something"; // Flag evaluation metadata - static final FlagMetadata flagMetadata = FlagMetadata.builder().build(); + static final ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); private EvaluationContext savedContext; diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index 8f96e610..c300daa0 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -11,7 +11,7 @@ class FlagMetadataTest { @DisplayName("Test metadata payload construction and retrieval") public void builder_validation() { // given - FlagMetadata flagMetadata = FlagMetadata.builder() + ImmutableMetadata flagMetadata = ImmutableMetadata.builder() .addString("string", "string") .addInteger("integer", 1) .addLong("long", 1L) @@ -44,7 +44,7 @@ public void builder_validation() { @DisplayName("Value type mismatch returns a null") public void value_type_validation() { // given - FlagMetadata flagMetadata = FlagMetadata.builder() + ImmutableMetadata flagMetadata = ImmutableMetadata.builder() .addString("string", "string") .build(); @@ -56,7 +56,7 @@ public void value_type_validation() { @DisplayName("A null is returned if key does not exist") public void notfound_error_validation() { // given - FlagMetadata flagMetadata = FlagMetadata.builder().build(); + ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); // then assertThat(flagMetadata.getBoolean("string")).isNull(); From bd3042ba0d15e0bd9a2f0d68693633adb555f6e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:18:09 +0000 Subject: [PATCH 108/134] chore(deps): update github/codeql-action digest to de74ca6 (#480) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 77f18c54..9fff3423 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@0ac18158d140a77edfc969babb80dbc82970eab3 + uses: github/codeql-action/init@de74ca621143bd07f97a91fcbd425e0f0553f239 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0ac18158d140a77edfc969babb80dbc82970eab3 + uses: github/codeql-action/analyze@de74ca621143bd07f97a91fcbd425e0f0553f239 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 984527e9..a6ebace9 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0ac18158d140a77edfc969babb80dbc82970eab3 + uses: github/codeql-action/init@de74ca621143bd07f97a91fcbd425e0f0553f239 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@0ac18158d140a77edfc969babb80dbc82970eab3 + uses: github/codeql-action/autobuild@de74ca621143bd07f97a91fcbd425e0f0553f239 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0ac18158d140a77edfc969babb80dbc82970eab3 + uses: github/codeql-action/analyze@de74ca621143bd07f97a91fcbd425e0f0553f239 From ea54bff9cc6a452fd6e329d0c3f2bad678e498a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 21:41:06 +0000 Subject: [PATCH 109/134] chore(deps): update github/codeql-action digest to c6dff34 (#481) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 9fff3423..33c344a0 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@de74ca621143bd07f97a91fcbd425e0f0553f239 + uses: github/codeql-action/init@c6dff3470ef81f6c675f720717ad354dce1b1d26 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@de74ca621143bd07f97a91fcbd425e0f0553f239 + uses: github/codeql-action/analyze@c6dff3470ef81f6c675f720717ad354dce1b1d26 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index a6ebace9..be392205 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@de74ca621143bd07f97a91fcbd425e0f0553f239 + uses: github/codeql-action/init@c6dff3470ef81f6c675f720717ad354dce1b1d26 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@de74ca621143bd07f97a91fcbd425e0f0553f239 + uses: github/codeql-action/autobuild@c6dff3470ef81f6c675f720717ad354dce1b1d26 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@de74ca621143bd07f97a91fcbd425e0f0553f239 + uses: github/codeql-action/analyze@c6dff3470ef81f6c675f720717ad354dce1b1d26 From b8b927ef4a418c32effb9fbc644667ec48a4ce7e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 05:46:22 +0000 Subject: [PATCH 110/134] chore(deps): update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.7.3.5 (#482) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6d637dd..25104ff1 100644 --- a/pom.xml +++ b/pom.xml @@ -373,7 +373,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.3.4 + 4.7.3.5 spotbugs-exclusions.xml From c3528da7024fa585ce265a620bca1f936ec508c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:46:52 +0000 Subject: [PATCH 111/134] chore(deps): update actions/setup-java digest to 1f2faad (#484) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 2caa5488..262cfdf5 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 + uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 33c344a0..6b64a3ca 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 + uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 709c7740..ab2d09f3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@45058d7f99afcd22834b58fde7cbfb7075eb48a2 + uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d with: java-version: '8' distribution: 'temurin' From dac79f0bd5f856230a86b7bc3e3842db92a5f8b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 21:50:17 +0000 Subject: [PATCH 112/134] chore(deps): update github/codeql-action digest to 8ba77ef (#485) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 6b64a3ca..b088ff98 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@c6dff3470ef81f6c675f720717ad354dce1b1d26 + uses: github/codeql-action/init@8ba77ef4d3284061307ef3908649b5e2ec7af11a with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c6dff3470ef81f6c675f720717ad354dce1b1d26 + uses: github/codeql-action/analyze@8ba77ef4d3284061307ef3908649b5e2ec7af11a diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index be392205..074a58b6 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c6dff3470ef81f6c675f720717ad354dce1b1d26 + uses: github/codeql-action/init@8ba77ef4d3284061307ef3908649b5e2ec7af11a with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@c6dff3470ef81f6c675f720717ad354dce1b1d26 + uses: github/codeql-action/autobuild@8ba77ef4d3284061307ef3908649b5e2ec7af11a - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c6dff3470ef81f6c675f720717ad354dce1b1d26 + uses: github/codeql-action/analyze@8ba77ef4d3284061307ef3908649b5e2ec7af11a From 6cd588b87a091ba11ccf3db8b2f72ffffbde358b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:55:34 +0000 Subject: [PATCH 113/134] chore(deps): update github/codeql-action digest to cff3d9e (#486) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index b088ff98..768dff1b 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@8ba77ef4d3284061307ef3908649b5e2ec7af11a + uses: github/codeql-action/init@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8ba77ef4d3284061307ef3908649b5e2ec7af11a + uses: github/codeql-action/analyze@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 074a58b6..3a514534 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8ba77ef4d3284061307ef3908649b5e2ec7af11a + uses: github/codeql-action/init@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@8ba77ef4d3284061307ef3908649b5e2ec7af11a + uses: github/codeql-action/autobuild@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8ba77ef4d3284061307ef3908649b5e2ec7af11a + uses: github/codeql-action/analyze@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e From 6cd208198ce786ce173eea2dbcffb6338ba28c86 Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Fri, 23 Jun 2023 15:23:58 -0400 Subject: [PATCH 114/134] chore: update copy and links on the readme (#488) Signed-off-by: Michael Beemer Co-authored-by: Todd Baert --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ba880dce..473d9350 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ We publish SBOMs with all of our releases as of 0.3.0. You can find them in Mave - support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider) - easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks) -- bool, string, numeric and object flag types +- bool, string, numeric, and object flag types - [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation ## ๐Ÿš€ Usage: @@ -165,11 +165,11 @@ public class MyProvider implements FeatureProvider { } ``` -See [here](https://openfeature.dev/docs/reference/technologies/server/java) for a catalog of available providers. +See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available providers. ### Hooks: -Hooks are a mechanism that allow for the addition of arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validation of the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. +A hook is a mechanism that allows for adding arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validating the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. ```java public class MyHook implements Hook { @@ -186,7 +186,7 @@ public class MyHook implements Hook { } ``` -See [here](https://openfeature.dev/docs/reference/technologies/server/java) for a catalog of available hooks. +See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available hooks. ### Logging: @@ -199,11 +199,11 @@ See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for ## โญ๏ธ Support the project - Give this repo a โญ๏ธ! -- Follow us social media: +- Follow us on social media: - Twitter: [@openfeature](https://twitter.com/openfeature) - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) - Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) -- For more check out our [community page](https://openfeature.dev/community/) +- For more, check out our [community page](https://openfeature.dev/community/) ## ๐Ÿค Contributing From 7f01deda5b5fb20ca126019e8553c4ac10ce460f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 22:26:14 +0000 Subject: [PATCH 115/134] chore(deps): update google-github-actions/release-please-action digest to 01f98cb (#489) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab2d09f3..3c0c6c1e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: # Release-please creates a PR that tracks all changes steps: - - uses: google-github-actions/release-please-action@51ee8ae2605bd5ce1cfdcc5938684908f1cd9f69 + - uses: google-github-actions/release-please-action@01f98cb9de537919302b1694069728b853c652ea id: release with: command: manifest From 8b9e0500924475bccd3f069f5967b5af59d50f12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:07:52 +0000 Subject: [PATCH 116/134] chore(deps): update amannn/action-semantic-pull-request digest to 00282d6 (#490) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/lint-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 28ce7e63..8f885bd8 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -18,6 +18,6 @@ jobs: name: Validate PR title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@3bb5af3c0c8f5e85d328728c1ab68dd6cefd03af + - uses: amannn/action-semantic-pull-request@00282d63cda40a6eaf3e9d0cbb1ac4384de896e8 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 693721e36c5b31adacd96afc55bc38ed53534db4 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 28 Jun 2023 10:40:10 -0400 Subject: [PATCH 117/134] feat: add empty constructors to data classes (#491) Signed-off-by: Todd Baert --- .../sdk/FlagEvaluationDetails.java | 10 ++-- .../openfeature/sdk/ProviderEvaluation.java | 17 +++++-- .../sdk/FlagEvaluationDetailsTest.java | 48 +++++++++++++++++++ .../sdk/ProviderEvaluationTest.java | 45 +++++++++++++++++ 4 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 src/test/java/dev/openfeature/sdk/FlagEvaluationDetailsTest.java create mode 100644 src/test/java/dev/openfeature/sdk/ProviderEvaluationTest.java diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java index 0a60565c..78e04c71 100644 --- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java +++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java @@ -1,17 +1,21 @@ package dev.openfeature.sdk; +import javax.annotation.Nullable; + +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; - -import javax.annotation.Nullable; +import lombok.NoArgsConstructor; /** - * Contains information about how the evaluation happened, including any resolved values. + * Contains information about how the provider resolved a flag, including the resolved value. * * @param the type of the flag being evaluated. */ @Data @Builder +@NoArgsConstructor +@AllArgsConstructor public class FlagEvaluationDetails implements BaseEvaluation { private String flagKey; diff --git a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java index 42441a8e..c4720263 100644 --- a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java +++ b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java @@ -1,12 +1,21 @@ package dev.openfeature.sdk; +import javax.annotation.Nullable; + +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; -import javax.annotation.Nullable; - -@SuppressWarnings("checkstyle:MissingJavadocType") -@Data @Builder +/** + * Contains information about how the a flag was evaluated, including the resolved value. + * + * @param the type of the flag being evaluated. + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class ProviderEvaluation implements BaseEvaluation { T value; @Nullable String variant; diff --git a/src/test/java/dev/openfeature/sdk/FlagEvaluationDetailsTest.java b/src/test/java/dev/openfeature/sdk/FlagEvaluationDetailsTest.java new file mode 100644 index 00000000..9a6df1a6 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/FlagEvaluationDetailsTest.java @@ -0,0 +1,48 @@ +package dev.openfeature.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class FlagEvaluationDetailsTest { + + @Test + @DisplayName("Should have empty constructor") + public void empty() { + FlagEvaluationDetails details = new FlagEvaluationDetails(); + assertNotNull(details); + } + + @Test + @DisplayName("Should have flagKey, value, variant, reason, errorCode, errorMessage, metadata constructor") + // removeing this constructor is a breaking change! + public void sevenArgConstructor() { + + String flagKey = "my-flag"; + Integer value = 100; + String variant = "1-hundred"; + Reason reason = Reason.DEFAULT; + ErrorCode errorCode = ErrorCode.GENERAL; + String errorMessage = "message"; + ImmutableMetadata metadata = ImmutableMetadata.builder().build(); + + FlagEvaluationDetails details = new FlagEvaluationDetails<>( + flagKey, + value, + variant, + reason.toString(), + errorCode, + errorMessage, + metadata); + + assertEquals(flagKey, details.getFlagKey()); + assertEquals(value, details.getValue()); + assertEquals(variant, details.getVariant()); + assertEquals(reason.toString(), details.getReason()); + assertEquals(errorCode, details.getErrorCode()); + assertEquals(errorMessage, details.getErrorMessage()); + assertEquals(metadata, details.getFlagMetadata()); + } +} diff --git a/src/test/java/dev/openfeature/sdk/ProviderEvaluationTest.java b/src/test/java/dev/openfeature/sdk/ProviderEvaluationTest.java new file mode 100644 index 00000000..16215dc1 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/ProviderEvaluationTest.java @@ -0,0 +1,45 @@ +package dev.openfeature.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ProviderEvaluationTest { + + @Test + @DisplayName("Should have empty constructor") + public void empty() { + ProviderEvaluation details = new ProviderEvaluation(); + assertNotNull(details); + } + + @Test + @DisplayName("Should have value, variant, reason, errorCode, errorMessage, metadata constructor") + // removeing this constructor is a breaking change! + public void sixArgConstructor() { + + Integer value = 100; + String variant = "1-hundred"; + Reason reason = Reason.DEFAULT; + ErrorCode errorCode = ErrorCode.GENERAL; + String errorMessage = "message"; + ImmutableMetadata metadata = ImmutableMetadata.builder().build(); + + ProviderEvaluation details = new ProviderEvaluation<>( + value, + variant, + reason.toString(), + errorCode, + errorMessage, + metadata); + + assertEquals(value, details.getValue()); + assertEquals(variant, details.getVariant()); + assertEquals(reason.toString(), details.getReason()); + assertEquals(errorCode, details.getErrorCode()); + assertEquals(errorMessage, details.getErrorMessage()); + assertEquals(metadata, details.getFlagMetadata()); + } +} From 207a221d4674c8cda7881ee41c1515048a0a059e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 01:36:12 +0000 Subject: [PATCH 118/134] chore(deps): update dependency com.google.guava:guava to v32.1.0-jre (#492) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 25104ff1..9d934fcc 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ com.google.guava guava - 32.0.1-jre + 32.1.0-jre test From 331d5110dab6e4806a5a45301d2f16c86d764644 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 20:50:33 +0000 Subject: [PATCH 119/134] chore(deps): update github/codeql-action digest to 46a6823 (#493) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 768dff1b..d79fdf39 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e + uses: github/codeql-action/init@46a6823b81f2d7c67ddf123851eea88365bc8a67 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e + uses: github/codeql-action/analyze@46a6823b81f2d7c67ddf123851eea88365bc8a67 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 3a514534..5823662e 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e + uses: github/codeql-action/init@46a6823b81f2d7c67ddf123851eea88365bc8a67 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e + uses: github/codeql-action/autobuild@46a6823b81f2d7c67ddf123851eea88365bc8a67 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cff3d9e3c9a51dfcf1ea2692cd1cd876dda6d71e + uses: github/codeql-action/analyze@46a6823b81f2d7c67ddf123851eea88365bc8a67 From a8e34100a02fdd102a605030b5be47796258ec23 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 13:02:50 +0000 Subject: [PATCH 120/134] chore(deps): update github/codeql-action digest to bcb460d (#495) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d79fdf39..7f21b727 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@46a6823b81f2d7c67ddf123851eea88365bc8a67 + uses: github/codeql-action/init@bcb460dab82ef96f9e4b3253df0235f78f92ed6a with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@46a6823b81f2d7c67ddf123851eea88365bc8a67 + uses: github/codeql-action/analyze@bcb460dab82ef96f9e4b3253df0235f78f92ed6a diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 5823662e..b9213dfc 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@46a6823b81f2d7c67ddf123851eea88365bc8a67 + uses: github/codeql-action/init@bcb460dab82ef96f9e4b3253df0235f78f92ed6a with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@46a6823b81f2d7c67ddf123851eea88365bc8a67 + uses: github/codeql-action/autobuild@bcb460dab82ef96f9e4b3253df0235f78f92ed6a - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@46a6823b81f2d7c67ddf123851eea88365bc8a67 + uses: github/codeql-action/analyze@bcb460dab82ef96f9e4b3253df0235f78f92ed6a From a7c7d4287960d6825a57d14d9878032d2d2170d0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:18:36 +0000 Subject: [PATCH 121/134] chore(deps): update dependency com.google.guava:guava to v32.1.1-jre (#494) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9d934fcc..7ce2d687 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ com.google.guava guava - 32.1.0-jre + 32.1.1-jre test From 9ddc9f1cb2c85c2d096a493342e429120ff36e92 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 19:26:56 +0000 Subject: [PATCH 122/134] chore(deps): update github/codeql-action digest to a42c0ca (#496) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 7f21b727..d93f6d76 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@bcb460dab82ef96f9e4b3253df0235f78f92ed6a + uses: github/codeql-action/init@a42c0ca9febc9b203c85be6deb4c3353aaeb176c with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@bcb460dab82ef96f9e4b3253df0235f78f92ed6a + uses: github/codeql-action/analyze@a42c0ca9febc9b203c85be6deb4c3353aaeb176c diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index b9213dfc..0b37ef4c 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@bcb460dab82ef96f9e4b3253df0235f78f92ed6a + uses: github/codeql-action/init@a42c0ca9febc9b203c85be6deb4c3353aaeb176c with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@bcb460dab82ef96f9e4b3253df0235f78f92ed6a + uses: github/codeql-action/autobuild@a42c0ca9febc9b203c85be6deb4c3353aaeb176c - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@bcb460dab82ef96f9e4b3253df0235f78f92ed6a + uses: github/codeql-action/analyze@a42c0ca9febc9b203c85be6deb4c3353aaeb176c From 2f028f699012fb160f156249ef9c85ecd8c2df13 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:28:48 +0000 Subject: [PATCH 123/134] chore(deps): update github/codeql-action digest to a2d725d (#497) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d93f6d76..aa202936 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@a42c0ca9febc9b203c85be6deb4c3353aaeb176c + uses: github/codeql-action/init@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a42c0ca9febc9b203c85be6deb4c3353aaeb176c + uses: github/codeql-action/analyze@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 0b37ef4c..073663a4 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@a42c0ca9febc9b203c85be6deb4c3353aaeb176c + uses: github/codeql-action/init@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@a42c0ca9febc9b203c85be6deb4c3353aaeb176c + uses: github/codeql-action/autobuild@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a42c0ca9febc9b203c85be6deb4c3353aaeb176c + uses: github/codeql-action/analyze@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 From 10bee74d16bba1bcaa110d58160e0f4eb9e7a960 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 20:05:33 +0000 Subject: [PATCH 124/134] chore(deps): update github/codeql-action digest to 84c0579 (#498) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index aa202936..2524d32f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 + uses: github/codeql-action/init@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 + uses: github/codeql-action/analyze@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 073663a4..60be57e1 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 + uses: github/codeql-action/init@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 + uses: github/codeql-action/autobuild@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@a2d725ddd07c1b5c68c8c4661e21db42b9fca9d7 + uses: github/codeql-action/analyze@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 From da0030408307b580fd912f5bf390b599f7a79024 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 12:33:56 +0000 Subject: [PATCH 125/134] fix(deps): update dependency io.cucumber:cucumber-bom to v7.13.0 (#499) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7ce2d687..e30d6740 100644 --- a/pom.xml +++ b/pom.xml @@ -160,7 +160,7 @@ io.cucumber cucumber-bom - 7.12.1 + 7.13.0 pom import From 4f6d7ff46d931c5f8bbdd454dda7c9b2c09578e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 18:49:35 +0000 Subject: [PATCH 126/134] chore(deps): update github/codeql-action digest to 85c77f1 (#500) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 2524d32f..d419e684 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 + uses: github/codeql-action/init@85c77f1dfc42a47cc98299e8779c151d2159b120 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 + uses: github/codeql-action/analyze@85c77f1dfc42a47cc98299e8779c151d2159b120 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 60be57e1..6cbfeed2 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 + uses: github/codeql-action/init@85c77f1dfc42a47cc98299e8779c151d2159b120 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 + uses: github/codeql-action/autobuild@85c77f1dfc42a47cc98299e8779c151d2159b120 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@84c057931e4ade1acbcd23d8e74c99b33b1c51d8 + uses: github/codeql-action/analyze@85c77f1dfc42a47cc98299e8779c151d2159b120 From b0201c7d4311f4c4ababa91984cf937b48ec7d35 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:40:28 +0000 Subject: [PATCH 127/134] chore(deps): update github/codeql-action digest to 6a07b2a (#502) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index d419e684..7bdaaf70 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@85c77f1dfc42a47cc98299e8779c151d2159b120 + uses: github/codeql-action/init@6a07b2ad4331abd7e6ff807d4df72417a61af4be with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@85c77f1dfc42a47cc98299e8779c151d2159b120 + uses: github/codeql-action/analyze@6a07b2ad4331abd7e6ff807d4df72417a61af4be diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 6cbfeed2..c9b359b9 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@85c77f1dfc42a47cc98299e8779c151d2159b120 + uses: github/codeql-action/init@6a07b2ad4331abd7e6ff807d4df72417a61af4be with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@85c77f1dfc42a47cc98299e8779c151d2159b120 + uses: github/codeql-action/autobuild@6a07b2ad4331abd7e6ff807d4df72417a61af4be - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@85c77f1dfc42a47cc98299e8779c151d2159b120 + uses: github/codeql-action/analyze@6a07b2ad4331abd7e6ff807d4df72417a61af4be From 2d3b6448963e794242babe016597fb5aa198afaf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 18:22:38 +0000 Subject: [PATCH 128/134] chore(deps): update actions/setup-java digest to 75c6561 (#503) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/merge.yml | 2 +- .github/workflows/pullrequest.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 262cfdf5..6a8a4be7 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d + uses: actions/setup-java@75c6561172d237e514a15dfd831cb331e5506d5e with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 7bdaaf70..fb7bc300 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 - uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d + uses: actions/setup-java@75c6561172d237e514a15dfd831cb331e5506d5e with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3c0c6c1e..611e7952 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@96f53100ba2a5449eb71d2e6604bbcd94b9449b5 - name: Set up JDK 8 if: ${{ steps.release.outputs.releases_created }} - uses: actions/setup-java@1f2faad7e0bc7efd1f6da4ca0a0f2b23b03a3a7d + uses: actions/setup-java@75c6561172d237e514a15dfd831cb331e5506d5e with: java-version: '8' distribution: 'temurin' From 00c812045926e627743ec5ff699acf6ea6797f8f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 00:59:17 +0000 Subject: [PATCH 129/134] chore(deps): update github/codeql-action digest to 95a5fda (#504) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index fb7bc300..4924bbe9 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@6a07b2ad4331abd7e6ff807d4df72417a61af4be + uses: github/codeql-action/init@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6a07b2ad4331abd7e6ff807d4df72417a61af4be + uses: github/codeql-action/analyze@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index c9b359b9..270a2f5a 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6a07b2ad4331abd7e6ff807d4df72417a61af4be + uses: github/codeql-action/init@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@6a07b2ad4331abd7e6ff807d4df72417a61af4be + uses: github/codeql-action/autobuild@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6a07b2ad4331abd7e6ff807d4df72417a61af4be + uses: github/codeql-action/analyze@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 From 893d0da6126ce49c73a90d20094a2e0123300ebb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 12:04:19 +0000 Subject: [PATCH 130/134] chore(deps): update github/codeql-action digest to 12aa0a6 (#505) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4924bbe9..5a1b2d35 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 + uses: github/codeql-action/init@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 + uses: github/codeql-action/analyze@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index 270a2f5a..dbbba159 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 + uses: github/codeql-action/init@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 + uses: github/codeql-action/autobuild@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95a5fda31a2c35fcb2e2f655a3c20dfab0016842 + uses: github/codeql-action/analyze@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 From bad5b0a7f5167d0b57bf502ce86b32b1c538746c Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 12 Jul 2023 12:22:16 -0400 Subject: [PATCH 131/134] feat: events (#476) * feat: events Signed-off-by: Todd Baert * fixup: fix bad import, fix test Signed-off-by: Todd Baert * fixup: add more coverage of internal Signed-off-by: Todd Baert * fixup: remove unused imports Signed-off-by: Todd Baert * fixup: unsed imports Signed-off-by: Todd Baert * fixup: make inner static Signed-off-by: Todd Baert * fixup: more tests, run ready immediately Signed-off-by: Todd Baert * fixup: improve reliability of error tests Signed-off-by: Todd Baert * Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java Co-authored-by: Giovanni Liva Signed-off-by: Todd Baert * fixup: review feedback, add comments Signed-off-by: Todd Baert * fixup: add provider repo tests, fitest warnings Signed-off-by: Todd Baert * Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java Co-authored-by: Kavindu Dodanduwa Signed-off-by: Todd Baert * fixup: shorten javadoc links, shutdown tasks, use methods refs Signed-off-by: Todd Baert * fixup: flaky test Signed-off-by: Todd Baert * Update src/main/java/dev/openfeature/sdk/OpenFeatureClient.java Co-authored-by: Justin Abrahms Signed-off-by: Todd Baert * fixup: feedback from justin Signed-off-by: Todd Baert * fixup: improve javadoc Signed-off-by: Todd Baert * fixup: test race condition fixes Signed-off-by: Todd Baert --------- Signed-off-by: Todd Baert Co-authored-by: Giovanni Liva Co-authored-by: Kavindu Dodanduwa Co-authored-by: Justin Abrahms --- pom.xml | 18 - src/main/java/dev/openfeature/sdk/Client.java | 2 +- .../java/dev/openfeature/sdk/EventBus.java | 64 ++ .../dev/openfeature/sdk/EventDetails.java | 28 + .../dev/openfeature/sdk/EventProvider.java | 95 +++ .../dev/openfeature/sdk/EventSupport.java | 174 +++++ .../dev/openfeature/sdk/FeatureProvider.java | 34 +- .../dev/openfeature/sdk/NoOpProvider.java | 6 + .../dev/openfeature/sdk/OpenFeatureAPI.java | 201 +++++- .../openfeature/sdk/OpenFeatureClient.java | 59 +- .../dev/openfeature/sdk/ProviderEvent.java | 8 + .../openfeature/sdk/ProviderEventDetails.java | 18 + .../openfeature/sdk/ProviderRepository.java | 134 ++-- .../dev/openfeature/sdk/ProviderState.java | 8 + .../openfeature/sdk/internal/ObjectUtils.java | 1 - .../openfeature/sdk/internal/TriConsumer.java | 38 ++ .../openfeature/sdk/EventProviderTest.java | 130 ++++ .../java/dev/openfeature/sdk/EventsTest.java | 599 ++++++++++++++++++ .../sdk/FlagEvaluationSpecTest.java | 10 +- .../sdk/InitializeBehaviorSpecTest.java | 24 +- .../java/dev/openfeature/sdk/LockingTest.java | 128 +++- .../sdk/ProviderRepositoryTest.java | 343 +++++----- .../dev/openfeature/sdk/ProviderSpecTest.java | 2 +- .../sdk/ShutdownBehaviorSpecTest.java | 4 +- .../sdk/fixtures/ProviderFixture.java | 43 +- .../sdk/internal/TriConsumerTest.java | 34 + .../sdk/testutils/TestEventsProvider.java | 99 +++ 27 files changed, 1940 insertions(+), 364 deletions(-) create mode 100644 src/main/java/dev/openfeature/sdk/EventBus.java create mode 100644 src/main/java/dev/openfeature/sdk/EventDetails.java create mode 100644 src/main/java/dev/openfeature/sdk/EventProvider.java create mode 100644 src/main/java/dev/openfeature/sdk/EventSupport.java create mode 100644 src/main/java/dev/openfeature/sdk/ProviderEvent.java create mode 100644 src/main/java/dev/openfeature/sdk/ProviderEventDetails.java create mode 100644 src/main/java/dev/openfeature/sdk/ProviderState.java create mode 100644 src/main/java/dev/openfeature/sdk/internal/TriConsumer.java create mode 100644 src/test/java/dev/openfeature/sdk/EventProviderTest.java create mode 100644 src/test/java/dev/openfeature/sdk/EventsTest.java create mode 100644 src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java create mode 100644 src/test/java/dev/openfeature/sdk/testutils/TestEventsProvider.java diff --git a/pom.xml b/pom.xml index e30d6740..af8807b8 100644 --- a/pom.xml +++ b/pom.xml @@ -178,21 +178,6 @@ - - org.codehaus.mojo - build-helper-maven-plugin - 3.4.0 - - - validate - get-cpu-count - - cpu-count - - - - - org.cyclonedx cyclonedx-maven-plugin @@ -261,9 +246,6 @@ ${surefireArgLine} - - ${cpu.count} - false ${testExclusions} diff --git a/src/main/java/dev/openfeature/sdk/Client.java b/src/main/java/dev/openfeature/sdk/Client.java index a4ccf26f..ebca0b13 100644 --- a/src/main/java/dev/openfeature/sdk/Client.java +++ b/src/main/java/dev/openfeature/sdk/Client.java @@ -5,7 +5,7 @@ /** * Interface used to resolve flags of varying types. */ -public interface Client extends Features { +public interface Client extends Features, EventBus { Metadata getMetadata(); /** diff --git a/src/main/java/dev/openfeature/sdk/EventBus.java b/src/main/java/dev/openfeature/sdk/EventBus.java new file mode 100644 index 00000000..d635e9ba --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/EventBus.java @@ -0,0 +1,64 @@ +package dev.openfeature.sdk; + +import java.util.function.Consumer; + +/** + * Interface for attaching event handlers. + */ +public interface EventBus { + + /** + * Add a handler for the {@link ProviderEvent#PROVIDER_READY} event. + * Shorthand for {@link #on(ProviderEvent, Consumer)} + * + * @param handler behavior to add with this event + * @return this + */ + T onProviderReady(Consumer handler); + + /** + * Add a handler for the {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} event. + * Shorthand for {@link #on(ProviderEvent, Consumer)} + * + * @param handler behavior to add with this event + * @return this + */ + T onProviderConfigurationChanged(Consumer handler); + + /** + * Add a handler for the {@link ProviderEvent#PROVIDER_STALE} event. + * Shorthand for {@link #on(ProviderEvent, Consumer)} + * + * @param handler behavior to add with this event + * @return this + */ + T onProviderError(Consumer handler); + + /** + * Add a handler for the {@link ProviderEvent#PROVIDER_ERROR} event. + * Shorthand for {@link #on(ProviderEvent, Consumer)} + * + * @param handler behavior to add with this event + * @return this + */ + T onProviderStale(Consumer handler); + + /** + * Add a handler for the specified {@link ProviderEvent}. + * + * @param event event type + * @param handler behavior to add with this event + * @return this + */ + T on(ProviderEvent event, Consumer handler); + + /** + * Remove the previously attached handler by reference. + * If the handler doesn't exists, no-op. + * + * @param event event type + * @param handler to be removed + * @return this + */ + T removeHandler(ProviderEvent event, Consumer handler); +} diff --git a/src/main/java/dev/openfeature/sdk/EventDetails.java b/src/main/java/dev/openfeature/sdk/EventDetails.java new file mode 100644 index 00000000..3f6db159 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/EventDetails.java @@ -0,0 +1,28 @@ +package dev.openfeature.sdk; + +import edu.umd.cs.findbugs.annotations.Nullable; +import lombok.Data; +import lombok.experimental.SuperBuilder; + +/** + * The details of a particular event. + */ +@Data @SuperBuilder(toBuilder = true) +public class EventDetails extends ProviderEventDetails { + private String clientName; + + static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails) { + return EventDetails.fromProviderEventDetails(providerEventDetails, null); + } + + static EventDetails fromProviderEventDetails( + ProviderEventDetails providerEventDetails, + @Nullable String clientName) { + return EventDetails.builder() + .clientName(clientName) + .flagsChanged(providerEventDetails.getFlagsChanged()) + .eventMetadata(providerEventDetails.getEventMetadata()) + .message(providerEventDetails.getMessage()) + .build(); + } +} diff --git a/src/main/java/dev/openfeature/sdk/EventProvider.java b/src/main/java/dev/openfeature/sdk/EventProvider.java new file mode 100644 index 00000000..de12b077 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/EventProvider.java @@ -0,0 +1,95 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.internal.TriConsumer; + +/** + * Abstract EventProvider. Providers must extend this class to support events. + * Emit events with {@link #emit(ProviderEvent, ProviderEventDetails)}. Please + * note that the SDK will automatically emit + * {@link ProviderEvent#PROVIDER_READY } or + * {@link ProviderEvent#PROVIDER_ERROR } accordingly when + * {@link FeatureProvider#initialize(EvaluationContext)} completes successfully + * or with error, so these events need not be emitted manually during + * initialization. + * + * @see FeatureProvider + */ +public abstract class EventProvider implements FeatureProvider { + + private TriConsumer onEmit = null; + + /** + * "Attach" this EventProvider to an SDK, which allows events to propagate from this provider. + * No-op if the same onEmit is already attached. + * + * @param onEmit the function to run when a provider emits events. + */ + void attach(TriConsumer onEmit) { + if (this.onEmit != null && this.onEmit != onEmit) { + // if we are trying to attach this provider to a different onEmit, something has gone wrong + throw new IllegalStateException("Provider " + this.getMetadata().getName() + " is already attached."); + } else { + this.onEmit = onEmit; + } + } + + /** + * "Detach" this EventProvider from an SDK, stopping propagation of all events. + */ + void detach() { + this.onEmit = null; + } + + /** + * Emit the specified {@link ProviderEvent}. + * + * @param event The event type + * @param details The details of the event + */ + public void emit(ProviderEvent event, ProviderEventDetails details) { + if (this.onEmit != null) { + this.onEmit.accept(this, event, details); + } + } + + /** + * Emit a {@link ProviderEvent#PROVIDER_READY} event. + * Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)} + * + * @param details The details of the event + */ + public void emitProviderReady(ProviderEventDetails details) { + emit(ProviderEvent.PROVIDER_READY, details); + } + + /** + * Emit a + * {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} + * event. Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)} + * + * @param details The details of the event + */ + public void emitProviderConfigurationChanged(ProviderEventDetails details) { + emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details); + } + + /** + * Emit a {@link ProviderEvent#PROVIDER_STALE} event. + * Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)} + * + * @param details The details of the event + */ + public void emitProviderStale(ProviderEventDetails details) { + emit(ProviderEvent.PROVIDER_STALE, details); + } + + /** + * Emit a {@link ProviderEvent#PROVIDER_ERROR} event. + * Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)} + * + * @param details The details of the event + */ + public void emitProviderError(ProviderEventDetails details) { + emit(ProviderEvent.PROVIDER_ERROR, details); + } +} diff --git a/src/main/java/dev/openfeature/sdk/EventSupport.java b/src/main/java/dev/openfeature/sdk/EventSupport.java new file mode 100644 index 00000000..6558f969 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/EventSupport.java @@ -0,0 +1,174 @@ +package dev.openfeature.sdk; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + +import edu.umd.cs.findbugs.annotations.Nullable; +import lombok.extern.slf4j.Slf4j; + +/** + * Util class for storing and running handlers. + */ +@Slf4j +class EventSupport { + + // we use a v4 uuid as a "placeholder" for anonymous clients, since + // ConcurrentHashMap doesn't support nulls + private static final String defaultClientUuid = UUID.randomUUID().toString(); + private static final ExecutorService taskExecutor = Executors.newCachedThreadPool(); + private final Map handlerStores = new ConcurrentHashMap<>(); + private final HandlerStore globalHandlerStore = new HandlerStore(); + + /** + * Run all the event handlers associated with this client name. + * If the client name is null, handlers attached to unnamed clients will run. + * + * @param clientName the client name to run event handlers for, or null + * @param event the event type + * @param eventDetails the event details + */ + public void runClientHandlers(@Nullable String clientName, ProviderEvent event, EventDetails eventDetails) { + clientName = Optional.ofNullable(clientName) + .orElse(defaultClientUuid); + + // run handlers if they exist + Optional.ofNullable(handlerStores.get(clientName)) + .filter(store -> Optional.of(store).isPresent()) + .map(store -> store.handlerMap.get(event)) + .ifPresent(handlers -> handlers + .forEach(handler -> runHandler(handler, eventDetails))); + } + + /** + * Run all the API (global) event handlers. + * + * @param event the event type + * @param eventDetails the event details + */ + public void runGlobalHandlers(ProviderEvent event, EventDetails eventDetails) { + globalHandlerStore.handlerMap.get(event) + .forEach(handler -> { + runHandler(handler, eventDetails); + }); + } + + /** + * Add a handler for the specified client name, or all unnamed clients. + * + * @param clientName the client name to add handlers for, or else the unnamed + * client + * @param event the event type + * @param handler the handler function to run + */ + public void addClientHandler(@Nullable String clientName, ProviderEvent event, Consumer handler) { + final String name = Optional.ofNullable(clientName) + .orElse(defaultClientUuid); + + // lazily create and cache a HandlerStore if it doesn't exist + HandlerStore store = Optional.ofNullable(this.handlerStores.get(name)) + .orElseGet(() -> { + HandlerStore newStore = new HandlerStore(); + this.handlerStores.put(name, newStore); + return newStore; + }); + store.addHandler(event, handler); + } + + /** + * Remove a client event handler for the specified event type. + * + * @param clientName the name of the client handler to remove, or null to remove + * from unnamed clients + * @param event the event type + * @param handler the handler ref to be removed + */ + public void removeClientHandler(String clientName, ProviderEvent event, Consumer handler) { + clientName = Optional.ofNullable(clientName) + .orElse(defaultClientUuid); + this.handlerStores.get(clientName).removeHandler(event, handler); + } + + /** + * Add a global event handler of the specified event type. + * + * @param event the event type + * @param handler the handler to be added + */ + public void addGlobalHandler(ProviderEvent event, Consumer handler) { + this.globalHandlerStore.addHandler(event, handler); + } + + /** + * Remove a global event handler for the specified event type. + * + * @param event the event type + * @param handler the handler ref to be removed + */ + public void removeGlobalHandler(ProviderEvent event, Consumer handler) { + this.globalHandlerStore.removeHandler(event, handler); + } + + /** + * Get all client names for which we have event handlers registered. + * + * @return set of client names + */ + public Set getAllClientNames() { + return this.handlerStores.keySet(); + } + + /** + * Run the passed handler on the taskExecutor. + * + * @param handler the handler to run + * @param eventDetails the event details + */ + public void runHandler(Consumer handler, EventDetails eventDetails) { + taskExecutor.submit(() -> { + try { + handler.accept(eventDetails); + } catch (Exception e) { + log.error("Exception in event handler {}", handler, e); + } + }); + } + + /** + * Stop the event handler task executor. + */ + public void shutdown() { + taskExecutor.shutdown(); + } + + // Handler store maintains a set of handlers for each event type. + // Each client in the SDK gets it's own handler store, which is lazily + // instantiated when a handler is added to that client. + static class HandlerStore { + + private final Map>> handlerMap; + + { + handlerMap = new ConcurrentHashMap>>(); + handlerMap.put(ProviderEvent.PROVIDER_READY, new ArrayList<>()); + handlerMap.put(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, new ArrayList<>()); + handlerMap.put(ProviderEvent.PROVIDER_ERROR, new ArrayList<>()); + handlerMap.put(ProviderEvent.PROVIDER_STALE, new ArrayList<>()); + } + + void addHandler(ProviderEvent event, Consumer handler) { + handlerMap.get(event).add(handler); + } + + void removeHandler(ProviderEvent event, Consumer handler) { + handlerMap.get(event).remove(handler); + } + } +} diff --git a/src/main/java/dev/openfeature/sdk/FeatureProvider.java b/src/main/java/dev/openfeature/sdk/FeatureProvider.java index 7df56a5f..933166fa 100644 --- a/src/main/java/dev/openfeature/sdk/FeatureProvider.java +++ b/src/main/java/dev/openfeature/sdk/FeatureProvider.java @@ -4,7 +4,9 @@ import java.util.List; /** - * The interface implemented by upstream flag providers to resolve flags for their service. + * The interface implemented by upstream flag providers to resolve flags for + * their service. If you want to support realtime events with your provider, you + * should extend {@link EventProvider} */ public interface FeatureProvider { Metadata getMetadata(); @@ -24,22 +26,28 @@ default List getProviderHooks() { ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx); /** - * This method is called before a provider is used to evaluate flags. Providers can overwrite this method, - * if they have special initialization needed prior being called for flag evaluation. + * This method is called before a provider is used to evaluate flags. Providers + * can overwrite this method, + * if they have special initialization needed prior being called for flag + * evaluation. *

- * It is ok, if the method is expensive as it is executed in the background. All runtime exceptions will be + * It is ok, if the method is expensive as it is executed in the background. All + * runtime exceptions will be * caught and logged. *

*/ - default void initialize() { + default void initialize(EvaluationContext evaluationContext) throws Exception { // Intentionally left blank } /** - * This method is called when a new provider is about to be used to evaluate flags, or the SDK is shut down. - * Providers can overwrite this method, if they have special shutdown actions needed. + * This method is called when a new provider is about to be used to evaluate + * flags, or the SDK is shut down. + * Providers can overwrite this method, if they have special shutdown actions + * needed. *

- * It is ok, if the method is expensive as it is executed in the background. All runtime exceptions will be + * It is ok, if the method is expensive as it is executed in the background. All + * runtime exceptions will be * caught and logged. *

*/ @@ -47,4 +55,14 @@ default void shutdown() { // Intentionally left blank } + /** + * Returns a representation of the current readiness of the provider. + * Providers which do not implement this method are assumed to be ready immediately. + * + * @return ProviderState + */ + default ProviderState getState() { + return ProviderState.READY; + } + } diff --git a/src/main/java/dev/openfeature/sdk/NoOpProvider.java b/src/main/java/dev/openfeature/sdk/NoOpProvider.java index c2e841a5..d3d9ca21 100644 --- a/src/main/java/dev/openfeature/sdk/NoOpProvider.java +++ b/src/main/java/dev/openfeature/sdk/NoOpProvider.java @@ -10,6 +10,12 @@ public class NoOpProvider implements FeatureProvider { @Getter private final String name = "No-op Provider"; + // The Noop provider is ALWAYS NOT_READY, otherwise READY handlers would run immediately when attached. + @Override + public ProviderState getState() { + return ProviderState.NOT_READY; + } + @Override public Metadata getMetadata() { return new Metadata() { diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java index 2e921a74..42ff4708 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java @@ -1,31 +1,33 @@ package dev.openfeature.sdk; -import dev.openfeature.sdk.internal.AutoCloseableLock; -import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; -import lombok.extern.slf4j.Slf4j; - -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import dev.openfeature.sdk.internal.AutoCloseableLock; +import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; +import lombok.extern.slf4j.Slf4j; /** - * A global singleton which holds base configuration for the OpenFeature library. + * A global singleton which holds base configuration for the OpenFeature + * library. * Configuration here will be shared across all {@link Client}s. */ @Slf4j -public class OpenFeatureAPI { +public class OpenFeatureAPI implements EventBus { // package-private multi-read/single-write lock - static AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock(); - static AutoCloseableReentrantReadWriteLock contextLock = new AutoCloseableReentrantReadWriteLock(); - + static AutoCloseableReentrantReadWriteLock lock = new AutoCloseableReentrantReadWriteLock(); + private EvaluationContext evaluationContext; private final List apiHooks; - private ProviderRepository providerRepository = new ProviderRepository(); - private EvaluationContext evaluationContext; + private EventSupport eventSupport = new EventSupport(); protected OpenFeatureAPI() { - this.apiHooks = new ArrayList<>(); + apiHooks = new ArrayList<>(); } private static class SingletonHolder { @@ -49,23 +51,34 @@ public Metadata getProviderMetadata(String clientName) { return getProvider(clientName).getMetadata(); } + /** + * {@inheritDoc} + */ public Client getClient() { return getClient(null, null); } + /** + * {@inheritDoc} + */ public Client getClient(@Nullable String name) { return getClient(name, null); } + /** + * {@inheritDoc} + */ public Client getClient(@Nullable String name, @Nullable String version) { - return new OpenFeatureClient(this, name, version); + return new OpenFeatureClient(this, + name, + version); } /** * {@inheritDoc} */ public void setEvaluationContext(EvaluationContext evaluationContext) { - try (AutoCloseableLock __ = contextLock.writeLockAutoCloseable()) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { this.evaluationContext = evaluationContext; } } @@ -74,7 +87,7 @@ public void setEvaluationContext(EvaluationContext evaluationContext) { * {@inheritDoc} */ public EvaluationContext getEvaluationContext() { - try (AutoCloseableLock __ = contextLock.readLockAutoCloseable()) { + try (AutoCloseableLock __ = lock.readLockAutoCloseable()) { return this.evaluationContext; } } @@ -83,7 +96,14 @@ public EvaluationContext getEvaluationContext() { * Set the default provider. */ public void setProvider(FeatureProvider provider) { - providerRepository.setProvider(provider); + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { + providerRepository.setProvider( + provider, + (p) -> attachEventProvider(p), + (p) -> emitReady(p), + (p) -> detachEventProvider(p), + (p, message) -> emitError(p, message)); + } } /** @@ -93,7 +113,37 @@ public void setProvider(FeatureProvider provider) { * @param provider The provider to set. */ public void setProvider(String clientName, FeatureProvider provider) { - providerRepository.setProvider(clientName, provider); + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { + providerRepository.setProvider(clientName, + provider, + this::attachEventProvider, + this::emitReady, + this::detachEventProvider, + this::emitError); + } + } + + private void attachEventProvider(FeatureProvider provider) { + if (provider instanceof EventProvider) { + ((EventProvider)provider).attach((p, event, details) -> { + runHandlersForProvider(p, event, details); + }); + } + } + + private void emitReady(FeatureProvider provider) { + runHandlersForProvider(provider, ProviderEvent.PROVIDER_READY, ProviderEventDetails.builder().build()); + } + + private void detachEventProvider(FeatureProvider provider) { + if (provider instanceof EventProvider) { + ((EventProvider)provider).detach(); + } + } + + private void emitError(FeatureProvider provider, String message) { + runHandlersForProvider(provider, ProviderEvent.PROVIDER_ERROR, + ProviderEventDetails.builder().message(message).build()); } /** @@ -117,7 +167,7 @@ public FeatureProvider getProvider(String name) { * {@inheritDoc} */ public void addHooks(Hook... hooks) { - try (AutoCloseableLock __ = hooksLock.writeLockAutoCloseable()) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { this.apiHooks.addAll(Arrays.asList(hooks)); } } @@ -126,7 +176,7 @@ public void addHooks(Hook... hooks) { * {@inheritDoc} */ public List getHooks() { - try (AutoCloseableLock __ = hooksLock.readLockAutoCloseable()) { + try (AutoCloseableLock __ = lock.readLockAutoCloseable()) { return this.apiHooks; } } @@ -135,19 +185,124 @@ public List getHooks() { * {@inheritDoc} */ public void clearHooks() { - try (AutoCloseableLock __ = hooksLock.writeLockAutoCloseable()) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { this.apiHooks.clear(); } } public void shutdown() { providerRepository.shutdown(); + eventSupport.shutdown(); } /** - * This method is only here for testing as otherwise all tests after the API shutdown test would fail. + * {@inheritDoc} */ - final void resetProviderRepository() { + @Override + public OpenFeatureAPI onProviderReady(Consumer handler) { + return this.on(ProviderEvent.PROVIDER_READY, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public OpenFeatureAPI onProviderConfigurationChanged(Consumer handler) { + return this.on(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public OpenFeatureAPI onProviderStale(Consumer handler) { + return this.on(ProviderEvent.PROVIDER_STALE, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public OpenFeatureAPI onProviderError(Consumer handler) { + return this.on(ProviderEvent.PROVIDER_ERROR, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public OpenFeatureAPI on(ProviderEvent event, Consumer handler) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { + this.eventSupport.addGlobalHandler(event, handler); + return this; + } + } + + /** + * {@inheritDoc} + */ + @Override + public OpenFeatureAPI removeHandler(ProviderEvent event, Consumer handler) { + this.eventSupport.removeGlobalHandler(event, handler); + return this; + } + + void removeHandler(String clientName, ProviderEvent event, Consumer handler) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { + eventSupport.removeClientHandler(clientName, event, handler); + } + } + + void addHandler(String clientName, ProviderEvent event, Consumer handler) { + try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) { + // if the provider is READY, run immediately + if (ProviderEvent.PROVIDER_READY.equals(event) + && ProviderState.READY.equals(this.providerRepository.getProvider(clientName).getState())) { + eventSupport.runHandler(handler, EventDetails.builder().clientName(clientName).build()); + } + eventSupport.addClientHandler(clientName, event, handler); + } + } + + /** + * This method is only here for testing as otherwise all tests after the API + * shutdown test would fail. + */ + final void reset() { providerRepository = new ProviderRepository(); + eventSupport = new EventSupport(); + } + + /** + * Runs the handlers associated with a particular provider. + * + * @param provider the provider from where this event originated + * @param event the event type + * @param details the event details + */ + private void runHandlersForProvider(FeatureProvider provider, ProviderEvent event, ProviderEventDetails details) { + try (AutoCloseableLock __ = lock.readLockAutoCloseable()) { + + List clientNamesForProvider = providerRepository + .getClientNamesForProvider(provider); + + // run the global handlers + eventSupport.runGlobalHandlers(event, EventDetails.fromProviderEventDetails(details)); + + // run the handlers associated with named clients for this provider + clientNamesForProvider.forEach(name -> { + eventSupport.runClientHandlers(name, event, EventDetails.fromProviderEventDetails(details, name)); + }); + + if (providerRepository.isDefaultProvider(provider)) { + // run handlers for clients that have no bound providers (since this is the default) + Set allClientNames = eventSupport.getAllClientNames(); + Set boundClientNames = providerRepository.getAllBoundClientNames(); + allClientNames.removeAll(boundClientNames); + allClientNames.forEach(name -> { + eventSupport.runClientHandlers(name, event, EventDetails.fromProviderEventDetails(details, name)); + }); + } + } } } diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java index 44febf77..05d79d02 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import dev.openfeature.sdk.exceptions.GeneralError; import dev.openfeature.sdk.exceptions.OpenFeatureError; @@ -33,13 +34,16 @@ public class OpenFeatureClient implements Client { private EvaluationContext evaluationContext; /** - * Client for evaluating the flag. There may be multiples of these floating - * around. + * Deprecated public constructor. Use OpenFeature.API.getClient() instead. * * @param openFeatureAPI Backing global singleton * @param name Name of the client (used by observability tools). * @param version Version of the client (used by observability tools). + * @deprecated Do not use this constructor. It's for internal use only. + * Clients created using it will not run event handlers. + * Use the OpenFeatureAPI's getClient factory method instead. */ + @Deprecated() // TODO: eventually we will make this non-public public OpenFeatureClient(OpenFeatureAPI openFeatureAPI, String name, String version) { this.openfeatureApi = openFeatureAPI; this.name = name; @@ -95,7 +99,6 @@ private FlagEvaluationDetails evaluateFlag(FlagValueType type, String key Map hints = Collections.unmodifiableMap(flagOptions.getHookHints()); ctx = ObjectUtils.defaultIfNull(ctx, () -> new ImmutableContext()); - FlagEvaluationDetails details = null; List mergedHooks = null; HookContext hookCtx = null; @@ -341,4 +344,54 @@ public FlagEvaluationDetails getObjectDetails(String key, Value defaultVa public Metadata getMetadata() { return () -> name; } + + /** + * {@inheritDoc} + */ + @Override + public Client onProviderReady(Consumer handler) { + return on(ProviderEvent.PROVIDER_READY, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public Client onProviderConfigurationChanged(Consumer handler) { + return on(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public Client onProviderError(Consumer handler) { + return on(ProviderEvent.PROVIDER_ERROR, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public Client onProviderStale(Consumer handler) { + return on(ProviderEvent.PROVIDER_STALE, handler); + } + + /** + * {@inheritDoc} + */ + @Override + public Client on(ProviderEvent event, Consumer handler) { + OpenFeatureAPI.getInstance().addHandler(name, event, handler); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Client removeHandler(ProviderEvent event, Consumer handler) { + OpenFeatureAPI.getInstance().removeHandler(name, event, handler); + return this; + } } diff --git a/src/main/java/dev/openfeature/sdk/ProviderEvent.java b/src/main/java/dev/openfeature/sdk/ProviderEvent.java new file mode 100644 index 00000000..dcefd606 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/ProviderEvent.java @@ -0,0 +1,8 @@ +package dev.openfeature.sdk; + +/** + * Provider event types. + */ +public enum ProviderEvent { + PROVIDER_READY, PROVIDER_CONFIGURATION_CHANGED, PROVIDER_ERROR, PROVIDER_STALE; +} diff --git a/src/main/java/dev/openfeature/sdk/ProviderEventDetails.java b/src/main/java/dev/openfeature/sdk/ProviderEventDetails.java new file mode 100644 index 00000000..149c92a7 --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/ProviderEventDetails.java @@ -0,0 +1,18 @@ +package dev.openfeature.sdk; + +import java.util.List; + +import javax.annotation.Nullable; + +import lombok.Data; +import lombok.experimental.SuperBuilder; + +/** + * The details of a particular event. + */ +@Data @SuperBuilder(toBuilder = true) +public class ProviderEventDetails { + @Nullable private List flagsChanged; + @Nullable private String message; + @Nullable private ImmutableMetadata eventMetadata; +} diff --git a/src/main/java/dev/openfeature/sdk/ProviderRepository.java b/src/main/java/dev/openfeature/sdk/ProviderRepository.java index 5a360eb6..0ff3b70b 100644 --- a/src/main/java/dev/openfeature/sdk/ProviderRepository.java +++ b/src/main/java/dev/openfeature/sdk/ProviderRepository.java @@ -1,24 +1,28 @@ package dev.openfeature.sdk; -import lombok.extern.slf4j.Slf4j; - +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.Nullable; + +import lombok.extern.slf4j.Slf4j; + @Slf4j class ProviderRepository { private final Map providers = new ConcurrentHashMap<>(); - private final ExecutorService taskExecutor = Executors.newCachedThreadPool(); - private final Map initializingNamedProviders = new ConcurrentHashMap<>(); private final AtomicReference defaultProvider = new AtomicReference<>(new NoOpProvider()); - private FeatureProvider initializingDefaultProvider; + private final ExecutorService taskExecutor = Executors.newCachedThreadPool(); /** * Return the default provider. @@ -37,14 +41,32 @@ public FeatureProvider getProvider(String name) { return Optional.ofNullable(name).map(this.providers::get).orElse(this.defaultProvider.get()); } + public List getClientNamesForProvider(FeatureProvider provider) { + return providers.entrySet().stream() + .filter(entry -> entry.getValue().equals(provider)) + .map(entry -> entry.getKey()).collect(Collectors.toList()); + } + + public Set getAllBoundClientNames() { + return providers.keySet(); + } + + public boolean isDefaultProvider(FeatureProvider provider) { + return this.getProvider().equals(provider); + } + /** * Set the default provider. */ - public void setProvider(FeatureProvider provider) { + public void setProvider(FeatureProvider provider, + Consumer afterSet, + Consumer afterInit, + Consumer afterShutdown, + BiConsumer afterError) { if (provider == null) { throw new IllegalArgumentException("Provider cannot be null"); } - initializeProvider(provider); + initializeProvider(null, provider, afterSet, afterInit, afterShutdown, afterError); } /** @@ -53,76 +75,51 @@ public void setProvider(FeatureProvider provider) { * @param clientName The name of the client. * @param provider The provider to set. */ - public void setProvider(String clientName, FeatureProvider provider) { + public void setProvider(String clientName, + FeatureProvider provider, + Consumer afterSet, + Consumer afterInit, + Consumer afterShutdown, + BiConsumer afterError) { if (provider == null) { throw new IllegalArgumentException("Provider cannot be null"); } if (clientName == null) { throw new IllegalArgumentException("clientName cannot be null"); } - initializeProvider(clientName, provider); - } - - private void initializeProvider(FeatureProvider provider) { - initializingDefaultProvider = provider; - initializeProvider(provider, this::updateDefaultProviderAfterInitialization); - } - - private void initializeProvider(String clientName, FeatureProvider provider) { - initializingNamedProviders.put(clientName, provider); - initializeProvider(provider, newProvider -> updateProviderAfterInit(clientName, newProvider)); - } - - private void initializeProvider(FeatureProvider provider, Consumer afterInitialization) { + initializeProvider(clientName, provider, afterSet, afterInit, afterShutdown, afterError); + } + + private void initializeProvider(@Nullable String clientName, + FeatureProvider newProvider, + Consumer afterSet, + Consumer afterInit, + Consumer afterShutdown, + BiConsumer afterError) { + // provider is set immediately, on this thread + FeatureProvider oldProvider = clientName != null + ? this.providers.put(clientName, newProvider) + : this.defaultProvider.getAndSet(newProvider); + afterSet.accept(newProvider); taskExecutor.submit(() -> { + // initialization happens in a different thread try { - if (!isProviderRegistered(provider)) { - provider.initialize(); + if (ProviderState.NOT_READY.equals(newProvider.getState())) { + newProvider.initialize(OpenFeatureAPI.getInstance().getEvaluationContext()); + afterInit.accept(newProvider); } - afterInitialization.accept(provider); + shutDownOld(oldProvider, afterShutdown); } catch (Exception e) { - log.error("Exception when initializing feature provider {}", provider.getClass().getName(), e); + log.error("Exception when initializing feature provider {}", newProvider.getClass().getName(), e); + afterError.accept(newProvider, e.getMessage()); } }); } - private void updateProviderAfterInit(String clientName, FeatureProvider newProvider) { - Optional - .ofNullable(initializingNamedProviders.get(clientName)) - .filter(initializingProvider -> initializingProvider.equals(newProvider)) - .ifPresent(provider -> updateNamedProviderAfterInitialization(clientName, provider)); - } - - private void updateDefaultProviderAfterInitialization(FeatureProvider initializedProvider) { - Optional - .ofNullable(this.initializingDefaultProvider) - .filter(initializingProvider -> initializingProvider.equals(initializedProvider)) - .ifPresent(this::replaceDefaultProvider); - } - - private void replaceDefaultProvider(FeatureProvider provider) { - FeatureProvider oldProvider = this.defaultProvider.getAndSet(provider); - if (isOldProviderNotBoundByName(oldProvider)) { - shutdownProvider(oldProvider); - } - } - - private boolean isOldProviderNotBoundByName(FeatureProvider oldProvider) { - return !this.providers.containsValue(oldProvider); - } - - private void updateNamedProviderAfterInitialization(String clientName, FeatureProvider initializedProvider) { - Optional - .ofNullable(this.initializingNamedProviders.get(clientName)) - .filter(initializingProvider -> initializingProvider.equals(initializedProvider)) - .ifPresent(provider -> replaceNamedProviderAndShutdownOldOne(clientName, provider)); - } - - private void replaceNamedProviderAndShutdownOldOne(String clientName, FeatureProvider provider) { - FeatureProvider oldProvider = this.providers.put(clientName, provider); - this.initializingNamedProviders.remove(clientName, provider); + private void shutDownOld(FeatureProvider oldProvider,Consumer afterShutdown) { if (!isProviderRegistered(oldProvider)) { shutdownProvider(oldProvider); + afterShutdown.accept(oldProvider); } } @@ -133,6 +130,7 @@ private boolean isProviderRegistered(FeatureProvider oldProvider) { private void shutdownProvider(FeatureProvider provider) { taskExecutor.submit(() -> { try { + // detachProviderEvents(provider); provider.shutdown(); } catch (Exception e) { log.error("Exception when shutting down feature provider {}", provider.getClass().getName(), e); @@ -141,7 +139,8 @@ private void shutdownProvider(FeatureProvider provider) { } /** - * Shutdowns this repository which includes shutting down all FeatureProviders that are registered, + * Shuts down this repository which includes shutting down all FeatureProviders + * that are registered, * including the default feature provider. */ public void shutdown() { @@ -149,7 +148,16 @@ public void shutdown() { .concat(Stream.of(this.defaultProvider.get()), this.providers.values().stream()) .distinct() .forEach(this::shutdownProvider); - setProvider(new NoOpProvider()); + setProvider(new NoOpProvider(), + (FeatureProvider fp) -> { + }, + (FeatureProvider fp) -> { + }, + (FeatureProvider fp) -> { + }, + (FeatureProvider fp, + String message) -> { + }); this.providers.clear(); taskExecutor.shutdown(); } diff --git a/src/main/java/dev/openfeature/sdk/ProviderState.java b/src/main/java/dev/openfeature/sdk/ProviderState.java new file mode 100644 index 00000000..6685f8fe --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/ProviderState.java @@ -0,0 +1,8 @@ +package dev.openfeature.sdk; + +/** + * Indicates the state of the provider. + */ +public enum ProviderState { + READY, NOT_READY, ERROR; +} diff --git a/src/main/java/dev/openfeature/sdk/internal/ObjectUtils.java b/src/main/java/dev/openfeature/sdk/internal/ObjectUtils.java index ff16422e..34caadae 100644 --- a/src/main/java/dev/openfeature/sdk/internal/ObjectUtils.java +++ b/src/main/java/dev/openfeature/sdk/internal/ObjectUtils.java @@ -69,5 +69,4 @@ public static List merge(List... sources) { .flatMap(Collection::stream) .collect(Collectors.toList()); } - } diff --git a/src/main/java/dev/openfeature/sdk/internal/TriConsumer.java b/src/main/java/dev/openfeature/sdk/internal/TriConsumer.java new file mode 100644 index 00000000..723f4aeb --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/internal/TriConsumer.java @@ -0,0 +1,38 @@ +package dev.openfeature.sdk.internal; + +import java.util.Objects; + +/** + * Like {@link java.util.function.BiConsumer} but with 3 params. + * + * @see java.util.function.BiConsumer + */ +@FunctionalInterface +public interface TriConsumer { + + /** + * Performs this operation on the given arguments. + * + * @param t the first input argument + * @param u the second input argument + * @param v the third input argument + */ + void accept(T t, U u, V v); + + /** + * Returns a composed {@code TriConsumer} that performs an additional operation. + * + * @param after the operation to perform after this operation + * @return a composed {@code TriConsumer} that performs in sequence this + * operation followed by the {@code after} operation + * @throws NullPointerException if {@code after} is null + */ + default TriConsumer andThen(TriConsumer after) { + Objects.requireNonNull(after); + + return (t, u, v) -> { + accept(t, u, v); + after.accept(t, u, v); + }; + } +} \ No newline at end of file diff --git a/src/test/java/dev/openfeature/sdk/EventProviderTest.java b/src/test/java/dev/openfeature/sdk/EventProviderTest.java new file mode 100644 index 00000000..cb73b529 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/EventProviderTest.java @@ -0,0 +1,130 @@ +package dev.openfeature.sdk; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import dev.openfeature.sdk.internal.TriConsumer; + +class EventProviderTest { + + @Test + @DisplayName("should run attached onEmit with emitters") + void emitsEventsWhenAttached() { + TestEventProvider eventProvider = new TestEventProvider(); + TriConsumer onEmit = mockOnEmit(); + eventProvider.attach(onEmit); + + ProviderEventDetails details = ProviderEventDetails.builder().build(); + eventProvider.emit(ProviderEvent.PROVIDER_READY, details); + eventProvider.emitProviderReady(details); + eventProvider.emitProviderConfigurationChanged(details); + eventProvider.emitProviderStale(details); + eventProvider.emitProviderError(details); + + verify(onEmit, times(2)).accept(eventProvider, ProviderEvent.PROVIDER_READY, details); + verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details); + verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_STALE, details); + verify(onEmit, times(1)).accept(eventProvider, ProviderEvent.PROVIDER_ERROR, details); + } + + @Test + @DisplayName("should do nothing with emitters if no onEmit attached") + void doesNotEmitsEventsWhenNotAttached() { + TestEventProvider eventProvider = new TestEventProvider(); + + // don't attach this emitter + TriConsumer onEmit = mockOnEmit(); + + ProviderEventDetails details = ProviderEventDetails.builder().build(); + eventProvider.emit(ProviderEvent.PROVIDER_READY, details); + eventProvider.emitProviderReady(details); + eventProvider.emitProviderConfigurationChanged(details); + eventProvider.emitProviderStale(details); + eventProvider.emitProviderError(details); + + // should not be called + verify(onEmit, never()).accept(any(), any(), any()); + } + + @Test + @DisplayName("should throw if second different onEmit attached") + void throwsWhenOnEmitDifferent() { + TestEventProvider eventProvider = new TestEventProvider(); + TriConsumer onEmit1 = mockOnEmit(); + TriConsumer onEmit2 = mockOnEmit(); + eventProvider.attach(onEmit1); + assertThrows(IllegalStateException.class, () -> eventProvider.attach(onEmit2)); + } + + + @Test + @DisplayName("should not throw if second same onEmit attached") + void doesNotThrowWhenOnEmitSame() { + TestEventProvider eventProvider = new TestEventProvider(); + TriConsumer onEmit1 = mockOnEmit(); + TriConsumer onEmit2 = onEmit1; + eventProvider.attach(onEmit1); + eventProvider.attach(onEmit2); // should not throw, same instance. noop + } + + + class TestEventProvider extends EventProvider { + + @Override + public Metadata getMetadata() { + return new Metadata() { + @Override + public String getName() { + return "TestEventProvider"; + } + }; + } + + @Override + public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, + EvaluationContext ctx) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getBooleanEvaluation'"); + } + + @Override + public ProviderEvaluation getStringEvaluation(String key, String defaultValue, + EvaluationContext ctx) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getStringEvaluation'"); + } + + @Override + public ProviderEvaluation getIntegerEvaluation(String key, Integer defaultValue, + EvaluationContext ctx) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getIntegerEvaluation'"); + } + + @Override + public ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, + EvaluationContext ctx) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getDoubleEvaluation'"); + } + + @Override + public ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, + EvaluationContext ctx) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getObjectEvaluation'"); + } + } + + @SuppressWarnings("unchecked") + private TriConsumer mockOnEmit() { + return (TriConsumer)mock(TriConsumer.class); + } +} \ No newline at end of file diff --git a/src/test/java/dev/openfeature/sdk/EventsTest.java b/src/test/java/dev/openfeature/sdk/EventsTest.java new file mode 100644 index 00000000..70f81657 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/EventsTest.java @@ -0,0 +1,599 @@ +package dev.openfeature.sdk; + +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.after; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatcher; + +import dev.openfeature.sdk.testutils.TestEventsProvider; +import io.cucumber.java.AfterAll; + +class EventsTest { + + private static final int TIMEOUT = 200; + private static final int INIT_DELAY = TIMEOUT / 2; + + @AfterAll + public static void resetDefaultProvider() { + OpenFeatureAPI.getInstance().setProvider(new NoOpProvider()); + } + + @Nested + class ApiEvents { + + @Nested + @DisplayName("named provider") + class NamedProvider { + + @Nested + @DisplayName("initialization") + class Initialization { + + @Test + @DisplayName("should fire initial READY event when provider init succeeds") + @Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally," + + " PROVIDER_READY handlers MUST run.") + void apiInitReady() { + final Consumer handler = (Consumer)mockHandler(); + final String name = "apiInitReady"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().onProviderReady(handler); + OpenFeatureAPI.getInstance().setProvider(name, provider); + verify(handler, timeout(TIMEOUT).atLeastOnce()) + .accept(any()); + } + + @Test + @DisplayName("should fire initial ERROR event when provider init errors") + @Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally," + + " PROVIDER_ERROR handlers MUST run.") + void apiInitError() { + final Consumer handler = mockHandler(); + final String name = "apiInitError"; + final String errMessage = "oh no!"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage); + OpenFeatureAPI.getInstance().onProviderError(handler); + OpenFeatureAPI.getInstance().setProvider(name, provider); + verify(handler, timeout(TIMEOUT)).accept(argThat(details -> { + return errMessage.equals(details.getMessage()); + })); + } + } + + @Nested + @DisplayName("provider events") + class ProviderEvents { + + @Test + @DisplayName("should propagate events") + @Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, " + + + "the associated client and API event handlers MUST run.") + void apiShouldPropagateEvents() { + final Consumer handler = mockHandler(); + final String name = "apiShouldPropagateEvents"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler); + + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build()); + verify(handler, timeout(TIMEOUT)).accept(any()); + } + + @Test + @DisplayName("should support all event types") + @Specification(number = "5.1.1", text = "The provider MAY define a mechanism for signaling the occurrence " + + "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, " + + "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.") + @Specification(number = "5.2.2", text = "The API MUST provide a function for associating handler functions" + + + " with a particular provider event type.") + void apiShouldSupportAllEventTypes() throws Exception { + final String name = "apiShouldSupportAllEventTypes"; + final Consumer handler1 = mockHandler(); + final Consumer handler2 = mockHandler(); + final Consumer handler3 = mockHandler(); + final Consumer handler4 = mockHandler(); + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + + OpenFeatureAPI.getInstance().onProviderReady(handler1); + OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler2); + OpenFeatureAPI.getInstance().onProviderStale(handler3); + OpenFeatureAPI.getInstance().onProviderError(handler4); + + Arrays.asList(ProviderEvent.values()).stream().forEach(eventType -> { + provider.mockEvent(eventType, ProviderEventDetails.builder().build()); + }); + + verify(handler1, timeout(TIMEOUT).atLeastOnce()).accept(any()); + verify(handler2, timeout(TIMEOUT).atLeastOnce()).accept(any()); + verify(handler3, timeout(TIMEOUT).atLeastOnce()).accept(any()); + verify(handler4, timeout(TIMEOUT).atLeastOnce()).accept(any()); + } + } + } + } + + @Nested + @DisplayName("client events") + class ClientEvents { + + @Nested + @DisplayName("default provider") + class DefaultProvider { + + @Nested + @DisplayName("provider events") + class ProviderEvents { + + @Test + @DisplayName("should propagate events for default provider and anonymous client") + @Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.") + void shouldPropagateDefaultAndAnon() { + final Consumer handler = mockHandler(); + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + // set provider before getting a client + OpenFeatureAPI.getInstance().setProvider(provider); + Client client = OpenFeatureAPI.getInstance().getClient(); + client.onProviderStale(handler); + + provider.mockEvent(ProviderEvent.PROVIDER_STALE, EventDetails.builder().build()); + verify(handler, timeout(TIMEOUT)).accept(any()); + } + + @Test + @DisplayName("should propagate events for default provider and named client") + @Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.") + void shouldPropagateDefaultAndNamed() { + final Consumer handler = mockHandler(); + final String name = "shouldPropagateDefaultAndNamed"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + // set provider before getting a client + OpenFeatureAPI.getInstance().setProvider(provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderStale(handler); + + provider.mockEvent(ProviderEvent.PROVIDER_STALE, EventDetails.builder().build()); + verify(handler, timeout(TIMEOUT)).accept(any()); + } + } + } + } + + @Nested + @DisplayName("named provider") + class NamedProvider { + + @Nested + @DisplayName("initialization") + class Initialization { + @Test + @DisplayName("should fire initial READY event when provider init succeeds after client retrieved") + @Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.") + void initReadyProviderBefore() throws InterruptedException { + final Consumer handler = mockHandler(); + final String name = "initReadyProviderBefore"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderReady(handler); + // set provider after getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + verify(handler, timeout(TIMEOUT).atLeastOnce()) + .accept(argThat(details -> details.getClientName().equals(name))); + } + + @Test + @DisplayName("should fire initial READY event when provider init succeeds before client retrieved") + @Specification(number = "5.3.1", text = "If the provider's initialize function terminates normally, PROVIDER_READY handlers MUST run.") + void initReadyProviderAfter() { + final Consumer handler = mockHandler(); + final String name = "initReadyProviderAfter"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + // set provider before getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderReady(handler); + verify(handler, timeout(TIMEOUT).atLeastOnce()) + .accept(argThat(details -> details.getClientName().equals(name))); + } + + @Test + @DisplayName("should fire initial ERROR event when provider init errors after client retrieved") + @Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.") + void initErrorProviderAfter() { + final Consumer handler = mockHandler(); + final String name = "initErrorProviderAfter"; + final String errMessage = "oh no!"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderError(handler); + // set provider after getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + verify(handler, timeout(TIMEOUT)).accept(argThat(details -> { + return name.equals(details.getClientName()) + && errMessage.equals(details.getMessage()); + })); + } + + @Test + @DisplayName("should fire initial ERROR event when provider init errors before client retrieved") + @Specification(number = "5.3.2", text = "If the provider's initialize function terminates abnormally, PROVIDER_ERROR handlers MUST run.") + void initErrorProviderBefore() { + final Consumer handler = mockHandler(); + final String name = "initErrorProviderBefore"; + final String errMessage = "oh no!"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY, true, errMessage); + // set provider after getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderError(handler); + verify(handler, timeout(TIMEOUT)).accept(argThat(details -> { + return name.equals(details.getClientName()) + && errMessage.equals(details.getMessage()); + })); + } + } + + @Nested + @DisplayName("provider events") + class ProviderEvents { + + @Test + @DisplayName("should propagate events when provider set before client retrieved") + @Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.") + void shouldPropagateBefore() { + final Consumer handler = mockHandler(); + final String name = "shouldPropagateBefore"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + // set provider before getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderConfigurationChanged(handler); + + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build()); + verify(handler, timeout(TIMEOUT)).accept(argThat(details -> details.getClientName().equals(name))); + } + + @Test + @DisplayName("should propagate events when provider set after client retrieved") + @Specification(number = "5.1.2", text = "When a provider signals the occurrence of a particular event, the associated client and API event handlers MUST run.") + void shouldPropagateAfter() { + + final Consumer handler = mockHandler(); + final String name = "shouldPropagateAfter"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderConfigurationChanged(handler); + // set provider after getting a client + OpenFeatureAPI.getInstance().setProvider(name, provider); + + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build()); + verify(handler, timeout(TIMEOUT)).accept(argThat(details -> details.getClientName().equals(name))); + } + + @Test + @DisplayName("should support all event types") + @Specification(number = "5.1.1", text = "The provider MAY define a mechanism for signaling the occurrence " + + "of one of a set of events, including PROVIDER_READY, PROVIDER_ERROR, " + + "PROVIDER_CONFIGURATION_CHANGED and PROVIDER_STALE, with a provider event details payload.") + @Specification(number = "5.2.1", text = "The client MUST provide a function for associating handler functions" + + + " with a particular provider event type.") + void shouldSupportAllEventTypes() throws Exception { + final String name = "shouldSupportAllEventTypes"; + final Consumer handler1 = mockHandler(); + final Consumer handler2 = mockHandler(); + final Consumer handler3 = mockHandler(); + final Consumer handler4 = mockHandler(); + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + + client.onProviderReady(handler1); + client.onProviderConfigurationChanged(handler2); + client.onProviderStale(handler3); + client.onProviderError(handler4); + + Arrays.asList(ProviderEvent.values()).stream().forEach(eventType -> { + provider.mockEvent(eventType, ProviderEventDetails.builder().build()); + }); + ArgumentMatcher nameMatches = (EventDetails details) -> details.getClientName() + .equals(name); + verify(handler1, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches)); + verify(handler2, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches)); + verify(handler3, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches)); + verify(handler4, timeout(TIMEOUT).atLeastOnce()).accept(argThat(nameMatches)); + } + } + } + + @Test + @DisplayName("shutdown provider should not run handlers") + void shouldNotRunHandlers() throws Exception { + final Consumer handler1 = mockHandler(); + final Consumer handler2 = mockHandler(); + final String name = "shouldNotRunHandlers"; + + TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY); + TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider1); + Client client = OpenFeatureAPI.getInstance().getClient(name); + + // attached handlers + OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler1); + client.onProviderConfigurationChanged(handler2); + + OpenFeatureAPI.getInstance().setProvider(name, provider2); + + // wait for the new provider to be ready and make sure things are cleaned up. + await().until(() -> provider1.isShutDown()); + + // fire old event + provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, EventDetails.builder().build()); + + // a bit of waiting here, but we want to make sure these are indeed never + // called. + verify(handler1, after(TIMEOUT).never()).accept(any()); + verify(handler2, never()).accept(any()); + } + + @Test + @DisplayName("other client handlers should not run") + @Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " + + "event handlers on clients which are not associated with that provider MUST NOT run.") + void otherClientHandlersShouldNotRun() throws Exception { + final String name1 = "otherClientHandlersShouldNotRun1"; + final String name2 = "otherClientHandlersShouldNotRun2"; + final Consumer handlerToRun = mockHandler(); + final Consumer handlerNotToRun = mockHandler(); + + TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY); + TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name1, provider1); + OpenFeatureAPI.getInstance().setProvider(name2, provider2); + + Client client1 = OpenFeatureAPI.getInstance().getClient(name1); + Client client2 = OpenFeatureAPI.getInstance().getClient(name2); + + client1.onProviderConfigurationChanged(handlerToRun); + client2.onProviderConfigurationChanged(handlerNotToRun); + + provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + + verify(handlerToRun, timeout(TIMEOUT)).accept(any()); + verify(handlerNotToRun, never()).accept(any()); + } + + @Test + @DisplayName("bound named client handlers should not run with default") + @Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " + + "event handlers on clients which are not associated with that provider MUST NOT run.") + void boundShouldNotRunWithDefault() throws Exception { + final String name = "boundShouldNotRunWithDefault"; + final Consumer handlerNotToRun = mockHandler(); + + TestEventsProvider namedProvider = new TestEventsProvider(INIT_DELAY); + TestEventsProvider defaultProvider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(defaultProvider); + + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderConfigurationChanged(handlerNotToRun); + OpenFeatureAPI.getInstance().setProvider(name, namedProvider); + + // await the new provider to make sure the old one is shut down + await().until(() -> namedProvider.getState().equals(ProviderState.READY)); + + // fire event on default provider + defaultProvider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + + verify(handlerNotToRun, after(TIMEOUT).never()).accept(any()); + OpenFeatureAPI.getInstance().setProvider(new NoOpProvider()); + } + + @Test + @DisplayName("unbound named client handlers should run with default") + @Specification(number = "5.1.3", text = "When a provider signals the occurrence of a particular event, " + + "event handlers on clients which are not associated with that provider MUST NOT run.") + void unboundShouldRunWithDefault() throws Exception { + final String name = "unboundShouldRunWithDefault"; + final Consumer handlerToRun = mockHandler(); + + TestEventsProvider defaultProvider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(defaultProvider); + + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderConfigurationChanged(handlerToRun); + + // await the new provider to make sure the old one is shut down + await().until(() -> defaultProvider.getState().equals(ProviderState.READY)); + + // fire event on default provider + defaultProvider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + + verify(handlerToRun, timeout(TIMEOUT)).accept(any()); + OpenFeatureAPI.getInstance().setProvider(new NoOpProvider()); + } + + @Test + @DisplayName("subsequent handlers run if earlier throws") + @Specification(number = "5.2.5", text = "If a handler function terminates abnormally, other handler functions MUST run.") + void handlersRunIfOneThrows() throws Exception { + final String name = "handlersRunIfOneThrows"; + final Consumer errorHandler = mockHandler(); + doThrow(new NullPointerException()).when(errorHandler).accept(any()); + final Consumer nextHandler = mockHandler(); + final Consumer lastHandler = mockHandler(); + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + + Client client1 = OpenFeatureAPI.getInstance().getClient(name); + + client1.onProviderConfigurationChanged(errorHandler); + client1.onProviderConfigurationChanged(nextHandler); + client1.onProviderConfigurationChanged(lastHandler); + + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + verify(errorHandler, timeout(TIMEOUT)).accept(any()); + verify(nextHandler, timeout(TIMEOUT)).accept(any()); + verify(lastHandler, timeout(TIMEOUT)).accept(any()); + } + + @Test + @DisplayName("should have all properties") + @Specification(number = "5.2.4", text = "The handler function MUST accept a event details parameter.") + @Specification(number = "5.2.3", text = "The event details MUST contain the client name associated with the event.") + void shouldHaveAllProperties() throws Exception { + final Consumer handler1 = mockHandler(); + final Consumer handler2 = mockHandler(); + final String name = "shouldHaveAllProperties"; + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + + // attached handlers + OpenFeatureAPI.getInstance().onProviderConfigurationChanged(handler1); + client.onProviderConfigurationChanged(handler2); + + List flagsChanged = Arrays.asList("flag"); + ImmutableMetadata metadata = ImmutableMetadata.builder().addInteger("int", 1).build(); + String message = "a message"; + ProviderEventDetails details = ProviderEventDetails.builder() + .eventMetadata(metadata) + .flagsChanged(flagsChanged) + .message(message) + .build(); + + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details); + + // both global and client handler should have all the fields. + verify(handler1, timeout(TIMEOUT)) + .accept(argThat((EventDetails eventDetails) -> { + return metadata.equals(eventDetails.getEventMetadata()) + // TODO: issue for client name in events + && flagsChanged.equals(eventDetails.getFlagsChanged()) + && message.equals(eventDetails.getMessage()); + })); + verify(handler2, timeout(TIMEOUT)) + .accept(argThat((EventDetails eventDetails) -> { + return metadata.equals(eventDetails.getEventMetadata()) + && flagsChanged.equals(eventDetails.getFlagsChanged()) + && message.equals(eventDetails.getMessage()) + && name.equals(eventDetails.getClientName()); + })); + } + + @Test + @DisplayName("if the provider is ready handlers must run immediately") + @Specification(number = "5.3.3", text = "PROVIDER_READY handlers attached after the provider is already in a ready state MUST run immediately.") + void readyMustRunImmediately() throws Exception { + final String name = "readyMustRunImmediately"; + final Consumer handler = mockHandler(); + + // provider which is already ready + TestEventsProvider provider = new TestEventsProvider(ProviderState.READY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + + // should run even thought handler was added after ready + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderReady(handler); + verify(handler, timeout(TIMEOUT)).accept(any()); + } + + @Test + @DisplayName("must persist across changes") + @Specification(number = "5.2.6", text = "Event handlers MUST persist across provider changes.") + void mustPersistAcrossChanges() throws Exception { + final String name = "mustPersistAcrossChanges"; + final Consumer handler = mockHandler(); + + TestEventsProvider provider1 = new TestEventsProvider(INIT_DELAY); + TestEventsProvider provider2 = new TestEventsProvider(INIT_DELAY); + + OpenFeatureAPI.getInstance().setProvider(name, provider1); + Client client = OpenFeatureAPI.getInstance().getClient(name); + client.onProviderConfigurationChanged(handler); + + provider1.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + ArgumentMatcher nameMatches = (EventDetails details) -> details.getClientName().equals(name); + + verify(handler, timeout(TIMEOUT).times(1)).accept(argThat(nameMatches)); + + // wait for the new provider to be ready. + OpenFeatureAPI.getInstance().setProvider(name, provider2); + await().until(() -> provider2.getState().equals(ProviderState.READY)); + + // verify that with the new provider under the same name, the handler is called + // again. + provider2.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + verify(handler, timeout(TIMEOUT).times(2)).accept(argThat(nameMatches)); + } + + @Nested + class HandlerRemoval { + @Test + @DisplayName("should not run removed events") + void removedEventsShouldNotRun() { + final String name = "removedEventsShouldNotRun"; + final Consumer handler1 = mockHandler(); + final Consumer handler2 = mockHandler(); + + TestEventsProvider provider = new TestEventsProvider(INIT_DELAY); + OpenFeatureAPI.getInstance().setProvider(name, provider); + Client client = OpenFeatureAPI.getInstance().getClient(name); + + // attached handlers + OpenFeatureAPI.getInstance().onProviderStale(handler1); + client.onProviderConfigurationChanged(handler2); + + OpenFeatureAPI.getInstance().removeHandler(ProviderEvent.PROVIDER_STALE, handler1); + client.removeHandler(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, handler2); + + // emit event + provider.mockEvent(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, ProviderEventDetails.builder().build()); + + // both global and client handlers should not run. + verify(handler1, after(TIMEOUT).never()).accept(any()); + verify(handler2, never()).accept(any()); + } + } + + @Specification(number = "5.1.4", text = "PROVIDER_ERROR events SHOULD populate the provider event details's error message field.") + @Test + void thisIsAProviderRequirement() { + } + + @SuppressWarnings("unchecked") + private static Consumer mockHandler() { + return mock(Consumer.class); + } +} diff --git a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java index 57f0c045..eb41fd95 100644 --- a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java @@ -62,20 +62,20 @@ void getApiInstance() { assertSame(OpenFeatureAPI.getInstance(), OpenFeatureAPI.getInstance()); } - @Specification(number="1.1.2", text="The API MUST provide a function to set the global provider singleton, which accepts an API-conformant provider implementation.") + @Specification(number="1.1.2.1", text="The API MUST define a provider mutator, a function to set the default provider, which accepts an API-conformant provider implementation.") @Test void provider() { FeatureProvider mockProvider = mock(FeatureProvider.class); FeatureProviderTestUtils.setFeatureProvider(mockProvider); assertThat(api.getProvider()).isEqualTo(mockProvider); } - @Specification(number="1.1.4", text="The API MUST provide a function for retrieving the metadata field of the configured provider.") + @Specification(number="1.1.5", text="The API MUST provide a function for retrieving the metadata field of the configured provider.") @Test void provider_metadata() { FeatureProviderTestUtils.setFeatureProvider(new DoSomethingProvider()); assertThat(api.getProviderMetadata().getName()).isEqualTo(DoSomethingProvider.name); } - @Specification(number="1.1.3", text="The API MUST provide a function to add hooks which accepts one or more API-conformant hooks, and appends them to the collection of any previously added hooks. When new hooks are added, previously added hooks are not removed.") + @Specification(number="1.1.4", text="The API MUST provide a function to add hooks which accepts one or more API-conformant hooks, and appends them to the collection of any previously added hooks. When new hooks are added, previously added hooks are not removed.") @Test void hook_addition() { Hook h1 = mock(Hook.class); Hook h2 = mock(Hook.class); @@ -89,7 +89,7 @@ void getApiInstance() { assertEquals(h2, api.getHooks().get(1)); } - @Specification(number="1.1.5", text="The API MUST provide a function for creating a client which accepts the following options: - name (optional): A logical string identifier for the client.") + @Specification(number="1.1.6", text="The API MUST provide a function for creating a client which accepts the following options: - name (optional): A logical string identifier for the client.") @Test void namedClient() { assertThatCode(() -> api.getClient("Sir Calls-a-lot")).doesNotThrowAnyException(); // TODO: Doesn't say that you can *get* the client name.. which seems useful? @@ -286,7 +286,7 @@ void getApiInstance() { @Specification(number="1.3.3", text="The client SHOULD guarantee the returned value of any typed flag evaluation method is of the expected type. If the value returned by the underlying provider implementation does not match the expected type, it's to be considered abnormal execution, and the supplied default value should be returned.") @Test void type_system_prevents_this() {} - @Specification(number="1.1.6", text="The client creation function MUST NOT throw, or otherwise abnormally terminate.") + @Specification(number="1.1.7", text="The client creation function MUST NOT throw, or otherwise abnormally terminate.") @Test void constructor_does_not_throw() {} @Specification(number="1.4.11", text="The client SHOULD provide asynchronous or non-blocking mechanisms for flag evaluation.") diff --git a/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java index 7061719f..0ab5e371 100644 --- a/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/InitializeBehaviorSpecTest.java @@ -21,12 +21,13 @@ class DefaultProvider { @Test @DisplayName("must call initialize function of the newly registered provider before using it for " + "flag evaluation") - void mustCallInitializeFunctionOfTheNewlyRegisteredProviderBeforeUsingItForFlagEvaluation() { + void mustCallInitializeFunctionOfTheNewlyRegisteredProviderBeforeUsingItForFlagEvaluation() throws Exception { FeatureProvider featureProvider = mock(FeatureProvider.class); + doReturn(ProviderState.NOT_READY).when(featureProvider).getState(); OpenFeatureAPI.getInstance().setProvider(featureProvider); - verify(featureProvider, timeout(1000)).initialize(); + verify(featureProvider, timeout(1000)).initialize(any()); } @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " @@ -35,14 +36,15 @@ void mustCallInitializeFunctionOfTheNewlyRegisteredProviderBeforeUsingItForFlagE + "the purposes for configuration or setup.") @Test @DisplayName("should catch exception thrown by the provider on initialization") - void shouldCatchExceptionThrownByTheProviderOnInitialization() { + void shouldCatchExceptionThrownByTheProviderOnInitialization() throws Exception { FeatureProvider featureProvider = mock(FeatureProvider.class); - doThrow(TestException.class).when(featureProvider).initialize(); + doReturn(ProviderState.NOT_READY).when(featureProvider).getState(); + doThrow(TestException.class).when(featureProvider).initialize(any()); assertThatCode(() -> OpenFeatureAPI.getInstance().setProvider(featureProvider)) .doesNotThrowAnyException(); - verify(featureProvider, timeout(1000)).initialize(); + verify(featureProvider, timeout(1000)).initialize(any()); } } @@ -54,12 +56,13 @@ class ProviderForNamedClient { @Test @DisplayName("must call initialize function of the newly registered named provider before using it " + "for flag evaluation") - void mustCallInitializeFunctionOfTheNewlyRegisteredNamedProviderBeforeUsingItForFlagEvaluation() { + void mustCallInitializeFunctionOfTheNewlyRegisteredNamedProviderBeforeUsingItForFlagEvaluation() throws Exception { FeatureProvider featureProvider = mock(FeatureProvider.class); + doReturn(ProviderState.NOT_READY).when(featureProvider).getState(); OpenFeatureAPI.getInstance().setProvider("clientName", featureProvider); - verify(featureProvider, timeout(1000)).initialize(); + verify(featureProvider, timeout(1000)).initialize(any()); } @Specification(number = "1.4.9", text = "Methods, functions, or operations on the client MUST NOT throw " @@ -68,14 +71,15 @@ void mustCallInitializeFunctionOfTheNewlyRegisteredNamedProviderBeforeUsingItFor + "the purposes for configuration or setup.") @Test @DisplayName("should catch exception thrown by the named client provider on initialization") - void shouldCatchExceptionThrownByTheNamedClientProviderOnInitialization() { + void shouldCatchExceptionThrownByTheNamedClientProviderOnInitialization() throws Exception { FeatureProvider featureProvider = mock(FeatureProvider.class); - doThrow(TestException.class).when(featureProvider).initialize(); + doReturn(ProviderState.NOT_READY).when(featureProvider).getState(); + doThrow(TestException.class).when(featureProvider).initialize(any()); assertThatCode(() -> OpenFeatureAPI.getInstance().setProvider("clientName", featureProvider)) .doesNotThrowAnyException(); - verify(featureProvider, timeout(1000)).initialize(); + verify(featureProvider, timeout(1000)).initialize(any()); } } } diff --git a/src/test/java/dev/openfeature/sdk/LockingTest.java b/src/test/java/dev/openfeature/sdk/LockingTest.java index 3d8d90c8..d9601e85 100644 --- a/src/test/java/dev/openfeature/sdk/LockingTest.java +++ b/src/test/java/dev/openfeature/sdk/LockingTest.java @@ -6,19 +6,20 @@ import static org.mockito.Mockito.when; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Consumer; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; class LockingTest { - + private static OpenFeatureAPI api; private OpenFeatureClient client; - private AutoCloseableReentrantReadWriteLock apiContextLock; - private AutoCloseableReentrantReadWriteLock apiHooksLock; + private AutoCloseableReentrantReadWriteLock apiLock; private AutoCloseableReentrantReadWriteLock clientContextLock; private AutoCloseableReentrantReadWriteLock clientHooksLock; @@ -31,10 +32,8 @@ static void beforeAll() { void beforeEach() { client = (OpenFeatureClient) api.getClient(); - apiContextLock = setupLock(apiContextLock, mockInnerReadLock(), mockInnerWriteLock()); - apiHooksLock = setupLock(apiHooksLock, mockInnerReadLock(), mockInnerWriteLock()); - OpenFeatureAPI.contextLock = apiContextLock; - OpenFeatureAPI.hooksLock = apiHooksLock; + apiLock = setupLock(apiLock, mockInnerReadLock(), mockInnerWriteLock()); + OpenFeatureAPI.lock = apiLock; clientContextLock = setupLock(clientContextLock, mockInnerReadLock(), mockInnerWriteLock()); clientHooksLock = setupLock(clientHooksLock, mockInnerReadLock(), mockInnerWriteLock()); @@ -42,6 +41,101 @@ void beforeEach() { client.hooksLock = clientHooksLock; } + @Nested + class EventsLocking { + + @Nested + class Api { + + @Test + void onShouldWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.on(ProviderEvent.PROVIDER_READY, handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderReadyShouldWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderReady(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderConfigurationChangedShouldWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderConfigurationChanged(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderStaleShouldWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderStale(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderErrorShouldWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderError(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + } + + @Nested + class Client { + + // Note that the API lock is used for adding client handlers, they are all added (indirectly) on the API object. + + @Test + void onShouldApiWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + client.on(ProviderEvent.PROVIDER_READY, handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderReadyShouldApiWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderReady(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderConfigurationChangedProviderReadyShouldApiWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderConfigurationChanged(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderStaleProviderReadyShouldApiWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderStale(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + + @Test + void onProviderErrorProviderReadyShouldApiWriteLockAndUnlock() { + Consumer handler = mock(Consumer.class); + api.onProviderError(handler); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); + } + } + } + + @Test void addHooksShouldWriteLockAndUnlock() { client.addHooks(new Hook() { @@ -51,8 +145,8 @@ void addHooksShouldWriteLockAndUnlock() { api.addHooks(new Hook() { }); - verify(apiHooksLock.writeLock()).lock(); - verify(apiHooksLock.writeLock()).unlock(); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); } @Test @@ -62,8 +156,8 @@ void getHooksShouldReadLockAndUnlock() { verify(clientHooksLock.readLock()).unlock(); api.getHooks(); - verify(apiHooksLock.readLock()).lock(); - verify(apiHooksLock.readLock()).unlock(); + verify(apiLock.readLock()).lock(); + verify(apiLock.readLock()).unlock(); } @Test @@ -73,8 +167,8 @@ void setContextShouldWriteLockAndUnlock() { verify(clientContextLock.writeLock()).unlock(); api.setEvaluationContext(new ImmutableContext()); - verify(apiContextLock.writeLock()).lock(); - verify(apiContextLock.writeLock()).unlock(); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); } @Test @@ -84,16 +178,16 @@ void getContextShouldReadLockAndUnlock() { verify(clientContextLock.readLock()).unlock(); api.getEvaluationContext(); - verify(apiContextLock.readLock()).lock(); - verify(apiContextLock.readLock()).unlock(); + verify(apiLock.readLock()).lock(); + verify(apiLock.readLock()).unlock(); } @Test void clearHooksShouldWriteLockAndUnlock() { api.clearHooks(); - verify(apiHooksLock.writeLock()).lock(); - verify(apiHooksLock.writeLock()).unlock(); + verify(apiLock.writeLock()).lock(); + verify(apiLock.writeLock()).unlock(); } private static ReentrantReadWriteLock.ReadLock mockInnerReadLock() { diff --git a/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java b/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java index 00c7949e..5b6dac1b 100644 --- a/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java +++ b/src/test/java/dev/openfeature/sdk/ProviderRepositoryTest.java @@ -1,35 +1,40 @@ package dev.openfeature.sdk; -import dev.openfeature.sdk.testutils.exception.TestException; -import lombok.SneakyThrows; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; +import static dev.openfeature.sdk.fixtures.ProviderFixture.createMockedErrorProvider; +import static dev.openfeature.sdk.fixtures.ProviderFixture.createMockedProvider; +import static dev.openfeature.sdk.fixtures.ProviderFixture.createMockedReadyProvider; +import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doDelayResponse; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import java.time.Duration; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Function; -import static dev.openfeature.sdk.fixtures.ProviderFixture.*; -import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doBlock; -import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doDelayResponse; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.awaitility.Awaitility.await; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import dev.openfeature.sdk.testutils.exception.TestException; class ProviderRepositoryTest { private static final String CLIENT_NAME = "client name"; private static final String ANOTHER_CLIENT_NAME = "another client name"; - private static final String FEATURE_KEY = "some key"; + private static final int TIMEOUT = 5000; private final ExecutorService executorService = Executors.newCachedThreadPool(); @@ -49,7 +54,8 @@ class DefaultProvider { @Test @DisplayName("should reject null as default provider") void shouldRejectNullAsDefaultProvider() { - assertThatCode(() -> providerRepository.setProvider(null)).isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> providerRepository.setProvider(null, mockAfterSet(), mockAfterInit(), + mockAfterShutdown(), mockAfterError())).isInstanceOf(IllegalArgumentException.class); } @Test @@ -60,78 +66,31 @@ void shouldHaveNoOpProviderSetAsDefaultOnInitialization() { @Test @DisplayName("should immediately return when calling the provider mutator") - void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + void shouldImmediatelyReturnWhenCallingTheProviderMutator() throws Exception { FeatureProvider featureProvider = createMockedProvider(); - doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(); + doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(new ImmutableContext()); await() .alias("wait for provider mutator to return") .pollDelay(Duration.ofMillis(1)) .atMost(Duration.ofSeconds(1)) .until(() -> { - providerRepository.setProvider(featureProvider); - verify(featureProvider, timeout(100)).initialize(); + providerRepository.setProvider(featureProvider, mockAfterSet(), mockAfterInit(), + mockAfterShutdown(), mockAfterError()); + verify(featureProvider, timeout(TIMEOUT)).initialize(any()); return true; }); - verify(featureProvider).initialize(); - } - - @Test - @DisplayName("should not return set provider if initialize has not yet been finished executing") - void shouldNotReturnSetProviderIfItsInitializeMethodHasNotYetBeenFinishedExecuting() { - CountDownLatch latch = new CountDownLatch(1); - FeatureProvider newProvider = createMockedProvider(); - doBlock(latch).when(newProvider).initialize(); - FeatureProvider oldProvider = providerRepository.getProvider(); - - providerRepository.setProvider(newProvider); - - FeatureProvider providerWhileInitialization = providerRepository.getProvider(); - latch.countDown(); - - assertThat(providerWhileInitialization).isEqualTo(oldProvider); - await() - .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .untilAsserted(() -> assertThat(providerRepository.getProvider()).isEqualTo(newProvider)); - verify(newProvider, timeout(100)).initialize(); - } - - @SneakyThrows - @Test - @DisplayName("should discard provider still initializing if a newer has finished before") - void shouldDiscardProviderStillInitializingIfANewerHasFinishedBefore() { - CountDownLatch latch = new CountDownLatch(1); - CountDownLatch testBlockingLatch = new CountDownLatch(1); - FeatureProvider blockedProvider = createBlockedProvider(latch, testBlockingLatch::countDown); - FeatureProvider fastProvider = createUnblockingProvider(latch); - - providerRepository.setProvider(blockedProvider); - providerRepository.setProvider(fastProvider); - - assertThat(testBlockingLatch.await(2, SECONDS)) - .as("blocking provider initialization not completed within 2 seconds") - .isTrue(); - - await() - .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .untilAsserted(() -> assertThat(providerRepository.getProvider()).isEqualTo(fastProvider)); - - verify(blockedProvider, timeout(100)).initialize(); - verify(fastProvider, timeout(100)).initialize(); + verify(featureProvider, timeout(TIMEOUT)).initialize(any()); } @Test @DisplayName("should avoid additional initialization call if provider has been initialized already") - void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() { - FeatureProvider provider = createMockedProvider(); - setFeatureProvider(CLIENT_NAME, provider); - + void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() throws Exception { + FeatureProvider provider = createMockedReadyProvider(); setFeatureProvider(provider); - - verify(provider).initialize(); + + verify(provider, never()).initialize(any()); } } @@ -141,90 +100,45 @@ class NamedProvider { @Test @DisplayName("should reject null as named provider") void shouldRejectNullAsNamedProvider() { - assertThatCode(() -> providerRepository.setProvider(CLIENT_NAME, null)).isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> providerRepository.setProvider(CLIENT_NAME, null, mockAfterSet(), mockAfterInit(), + mockAfterShutdown(), mockAfterError())) + .isInstanceOf(IllegalArgumentException.class); } @Test @DisplayName("should reject null as client name") void shouldRejectNullAsDefaultProvider() { NoOpProvider provider = new NoOpProvider(); - assertThatCode(() -> providerRepository.setProvider(null, provider)).isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> providerRepository.setProvider(null, provider, mockAfterSet(), mockAfterInit(), + mockAfterShutdown(), mockAfterError())) + .isInstanceOf(IllegalArgumentException.class); } @Test @DisplayName("should immediately return when calling the named client provider mutator") - void shouldImmediatelyReturnWhenCallingTheNamedClientProviderMutator() { + void shouldImmediatelyReturnWhenCallingTheNamedClientProviderMutator() throws Exception { FeatureProvider featureProvider = createMockedProvider(); - doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(); + doDelayResponse(Duration.ofSeconds(10)).when(featureProvider).initialize(any()); await() .alias("wait for provider mutator to return") .pollDelay(Duration.ofMillis(1)) .atMost(Duration.ofSeconds(1)) .until(() -> { - providerRepository.setProvider("named client", featureProvider); - verify(featureProvider, timeout(1000)).initialize(); + providerRepository.setProvider("named client", featureProvider, mockAfterSet(), + mockAfterInit(), mockAfterShutdown(), mockAfterError()); + verify(featureProvider, timeout(TIMEOUT)).initialize(any()); return true; }); } - @Test - @DisplayName("should not return set provider if it's initialization has not yet been finished executing") - void shouldNotReturnSetProviderIfItsInitializeMethodHasNotYetBeenFinishedExecuting() { - CountDownLatch latch = new CountDownLatch(1); - FeatureProvider newProvider = createMockedProvider(); - doBlock(latch).when(newProvider).initialize(); - FeatureProvider oldProvider = createMockedProvider(); - setFeatureProvider(CLIENT_NAME, oldProvider); - - providerRepository.setProvider(CLIENT_NAME, newProvider); - FeatureProvider providerWhileInitialization = getNamedProvider(); - latch.countDown(); - - assertThat(providerWhileInitialization).isEqualTo(oldProvider); - await() - .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .untilAsserted(() -> assertThat(getNamedProvider()).isEqualTo(newProvider)); - verify(newProvider, timeout(100)).initialize(); - } - - @SneakyThrows - @Test - @DisplayName("should discard provider still initializing if a newer has finished before") - void shouldDiscardProviderStillInitializingIfANewerHasFinishedBefore() { - String clientName = "clientName"; - CountDownLatch latch = new CountDownLatch(1); - CountDownLatch testBlockingLatch = new CountDownLatch(1); - FeatureProvider blockedProvider = createBlockedProvider(latch, testBlockingLatch::countDown); - FeatureProvider unblockingProvider = createUnblockingProvider(latch); - - providerRepository.setProvider(clientName, blockedProvider); - providerRepository.setProvider(clientName, unblockingProvider); - - assertThat(testBlockingLatch.await(2, SECONDS)) - .as("blocking provider initialization not completed within 2 seconds") - .isTrue(); - - await() - .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .untilAsserted(() -> assertThat(providerRepository.getProvider(clientName)) - .isEqualTo(unblockingProvider)); - - verify(blockedProvider, timeout(100)).initialize(); - verify(unblockingProvider, timeout(100)).initialize(); - } - @Test @DisplayName("should avoid additional initialization call if provider has been initialized already") - void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() { - FeatureProvider provider = createMockedProvider(); - setFeatureProvider(provider); - + void shouldAvoidAdditionalInitializationCallIfProviderHasBeenInitializedAlready() throws Exception { + FeatureProvider provider = createMockedReadyProvider(); setFeatureProvider(CLIENT_NAME, provider); - verify(provider).initialize(); + verify(provider, never()).initialize(any()); } } } @@ -237,43 +151,22 @@ class DefaultProvider { @Test @DisplayName("should immediately return when calling the provider mutator") - void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + void shouldImmediatelyReturnWhenCallingTheProviderMutator() throws Exception { FeatureProvider newProvider = createMockedProvider(); - doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(); + doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(any()); await() .alias("wait for provider mutator to return") .pollDelay(Duration.ofMillis(1)) .atMost(Duration.ofSeconds(1)) .until(() -> { - providerRepository.setProvider(newProvider); - verify(newProvider, timeout(100)).initialize(); + providerRepository.setProvider(newProvider, mockAfterSet(), mockAfterInit(), + mockAfterShutdown(), mockAfterError()); + verify(newProvider, timeout(TIMEOUT)).initialize(any()); return true; }); - verify(newProvider).initialize(); - } - - @Test - @DisplayName("should use old provider if replacing one has not yet been finished initializing") - void shouldUseOldProviderIfReplacingOneHasNotYetBeenFinishedInitializing() { - CountDownLatch latch = new CountDownLatch(1); - FeatureProvider newProvider = createMockedProvider(); - doBlock(latch).when(newProvider).initialize(); - FeatureProvider oldProvider = createMockedProvider(); - - setFeatureProvider(oldProvider); - providerRepository.setProvider(newProvider); - - providerRepository.getProvider().getBooleanEvaluation("some key", true, null); - latch.countDown(); - - await() - .atMost(Duration.ofSeconds(1)) - .pollDelay(Duration.ofMillis(1)) - .untilAsserted(() -> assertThat(getProvider()).isEqualTo(newProvider)); - verify(oldProvider, timeout(100)).getBooleanEvaluation(any(), any(), any()); - verify(newProvider, never()).getBooleanEvaluation(any(), any(), any()); + verify(newProvider, timeout(TIMEOUT)).initialize(any()); } @Test @@ -295,12 +188,13 @@ class NamedProvider { @Test @DisplayName("should immediately return when calling the provider mutator") - void shouldImmediatelyReturnWhenCallingTheProviderMutator() { + void shouldImmediatelyReturnWhenCallingTheProviderMutator() throws Exception { FeatureProvider newProvider = createMockedProvider(); - doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(); + doDelayResponse(Duration.ofSeconds(10)).when(newProvider).initialize(any()); Future providerMutation = executorService - .submit(() -> providerRepository.setProvider(CLIENT_NAME, newProvider)); + .submit(() -> providerRepository.setProvider(CLIENT_NAME, newProvider, mockAfterSet(), + mockAfterInit(), mockAfterShutdown(), mockAfterError())); await() .alias("wait for provider mutator to return") @@ -309,34 +203,13 @@ void shouldImmediatelyReturnWhenCallingTheProviderMutator() { .until(providerMutation::isDone); } - @Test - @DisplayName("should use old provider if replacement one has not yet been finished initializing") - void shouldUseOldProviderIfReplacementHasNotYetBeenFinishedInitializing() { - CountDownLatch latch = new CountDownLatch(1); - FeatureProvider newProvider = createMockedProvider(); - doBlock(latch).when(newProvider).initialize(); - FeatureProvider oldProvider = createMockedProvider(); - - setFeatureProvider(CLIENT_NAME, oldProvider); - providerRepository.setProvider(CLIENT_NAME, newProvider); - - providerRepository.getProvider(CLIENT_NAME).getBooleanEvaluation(FEATURE_KEY, true, null); - latch.countDown(); - - await() - .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .untilAsserted(() -> assertThat(getNamedProvider()).isEqualTo(newProvider)); - verify(oldProvider, timeout(100)).getBooleanEvaluation(eq(FEATURE_KEY), any(), any()); - verify(newProvider, never()).getBooleanEvaluation(any(), any(), any()); - } - @Test @DisplayName("should not call shutdown if replaced provider is bound to multiple names") - void shouldNotCallShutdownIfReplacedProviderIsBoundToMultipleNames() { + void shouldNotCallShutdownIfReplacedProviderIsBoundToMultipleNames() throws InterruptedException { FeatureProvider oldProvider = createMockedProvider(); FeatureProvider newProvider = createMockedProvider(); setFeatureProvider(CLIENT_NAME, oldProvider); + setFeatureProvider(ANOTHER_CLIENT_NAME, oldProvider); setFeatureProvider(CLIENT_NAME, newProvider); @@ -366,7 +239,48 @@ void shouldNotThrowExceptionIfProviderThrowsOneOnShutdown() { assertThatCode(() -> setFeatureProvider(new NoOpProvider())).doesNotThrowAnyException(); - verify(provider).shutdown(); + verify(provider, timeout(TIMEOUT)).shutdown(); + } + } + + @Nested + class LifecyleLambdas { + @Test + @DisplayName("should run afterSet, afterInit, afterShutdown on successful set/init") + @SuppressWarnings("unchecked") + void shouldRunLambdasOnSuccessful() { + Consumer afterSet = mock(Consumer.class); + Consumer afterInit = mock(Consumer.class); + Consumer afterShutdown = mock(Consumer.class); + BiConsumer afterError = mock(BiConsumer.class); + + FeatureProvider oldProvider = providerRepository.getProvider(); + FeatureProvider featureProvider1 = createMockedProvider(); + FeatureProvider featureProvider2 = createMockedProvider(); + + setFeatureProvider(featureProvider1, afterSet, afterInit, afterShutdown, afterError); + setFeatureProvider(featureProvider2); + verify(afterSet, timeout(TIMEOUT)).accept(featureProvider1); + verify(afterInit, timeout(TIMEOUT)).accept(featureProvider1); + verify(afterShutdown, timeout(TIMEOUT)).accept(oldProvider); + verify(afterError, never()).accept(any(), any()); + } + + @Test + @DisplayName("should run afterSet, afterError on unsuccessful set/init") + @SuppressWarnings("unchecked") + void shouldRunLambdasOnError() throws Exception { + Consumer afterSet = mock(Consumer.class); + Consumer afterInit = mock(Consumer.class); + Consumer afterShutdown = mock(Consumer.class); + BiConsumer afterError = mock(BiConsumer.class); + + FeatureProvider errorFeatureProvider = createMockedErrorProvider(); + + setFeatureProvider(errorFeatureProvider, afterSet, afterInit, afterShutdown, afterError); + verify(afterSet, timeout(TIMEOUT)).accept(errorFeatureProvider); + verify(afterInit, never()).accept(any());; + verify(afterError, timeout(TIMEOUT)).accept(eq(errorFeatureProvider), any()); } } } @@ -385,31 +299,34 @@ void shouldShutdownAllFeatureProvidersOnShutdown() { await() .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) + .atMost(Duration.ofSeconds(TIMEOUT)) .untilAsserted(() -> { assertThat(providerRepository.getProvider()).isInstanceOf(NoOpProvider.class); assertThat(providerRepository.getProvider(CLIENT_NAME)).isInstanceOf(NoOpProvider.class); assertThat(providerRepository.getProvider(ANOTHER_CLIENT_NAME)).isInstanceOf(NoOpProvider.class); }); - verify(featureProvider1).shutdown(); - verify(featureProvider2).shutdown(); + verify(featureProvider1, timeout(TIMEOUT)).shutdown(); + verify(featureProvider2, timeout(TIMEOUT)).shutdown(); } - private FeatureProvider getProvider() { - return providerRepository.getProvider(); + private void setFeatureProvider(FeatureProvider provider) { + providerRepository.setProvider(provider, mockAfterSet(), mockAfterInit(), mockAfterShutdown(), + mockAfterError()); + waitForSettingProviderHasBeenCompleted(ProviderRepository::getProvider, provider); } - private FeatureProvider getNamedProvider() { - return providerRepository.getProvider(CLIENT_NAME); - } - private void setFeatureProvider(FeatureProvider provider) { - providerRepository.setProvider(provider); + private void setFeatureProvider(FeatureProvider provider, Consumer afterSet, + Consumer afterInit, Consumer afterShutdown, + BiConsumer afterError) { + providerRepository.setProvider(provider, afterSet, afterInit, afterShutdown, + afterError); waitForSettingProviderHasBeenCompleted(ProviderRepository::getProvider, provider); } private void setFeatureProvider(String namedProvider, FeatureProvider provider) { - providerRepository.setProvider(namedProvider, provider); + providerRepository.setProvider(namedProvider, provider, mockAfterSet(), mockAfterInit(), mockAfterShutdown(), + mockAfterError()); waitForSettingProviderHasBeenCompleted(repository -> repository.getProvider(namedProvider), provider); } @@ -418,8 +335,30 @@ private void waitForSettingProviderHasBeenCompleted( FeatureProvider provider) { await() .pollDelay(Duration.ofMillis(1)) - .atMost(Duration.ofSeconds(1)) - .until(() -> extractor.apply(providerRepository) == provider); + .atMost(Duration.ofSeconds(5)) + .until(() -> { + return extractor.apply(providerRepository) == provider; + }); + } + + private Consumer mockAfterSet() { + return fp -> { + }; + } + + private Consumer mockAfterInit() { + return fp -> { + }; + } + + private Consumer mockAfterShutdown() { + return fp -> { + }; + } + + private BiConsumer mockAfterError() { + return (fp, message) -> { + }; } } diff --git a/src/test/java/dev/openfeature/sdk/ProviderSpecTest.java b/src/test/java/dev/openfeature/sdk/ProviderSpecTest.java index 31a6a5e8..f5e5e6a4 100644 --- a/src/test/java/dev/openfeature/sdk/ProviderSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/ProviderSpecTest.java @@ -18,7 +18,7 @@ void name_accessor() { @Specification(number = "2.2.2.1", text = "The feature provider interface MUST define methods for typed " + "flag resolution, including boolean, numeric, string, and structure.") @Specification(number = "2.2.3", text = "In cases of normal execution, the `provider` MUST populate the `resolution details` structure's `value` field with the resolved flag value.") - @Specification(number = "2.2.1", text = "The `feature provider` interface MUST define methods to resolve flag values, with parameters `flag key` (string, required), `default value` (boolean | number | string | structure, required) + and `evaluation context` (optional), which returns a `resolution details` structure.") + @Specification(number = "2.2.1", text = "The `feature provider` interface MUST define methods to resolve flag values, with parameters `flag key` (string, required), `default value` (boolean | number | string | structure, required) and `evaluation context` (optional), which returns a `resolution details` structure.") @Specification(number = "2.2.8.1", text = "The `resolution details` structure SHOULD accept a generic argument (or use an equivalent language feature) which indicates the type of the wrapped `value` field.") @Test void flag_value_set() { diff --git a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java index d191c8c4..e470819f 100644 --- a/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/ShutdownBehaviorSpecTest.java @@ -89,7 +89,7 @@ void shouldCatchExceptionThrownByTheNamedClientProviderOnShutdown() { @Nested class General { - @Specification(number = "1.6.1", text = "The API MUST define a shutdown function which, when called, must call the respective shutdown function on the active provider.") + @Specification(number = "1.6.1", text = "The API MUST define a mechanism to propagate a shutdown request to active providers.") @Test @DisplayName("must shutdown all providers on shutting down api") void mustShutdownAllProvidersOnShuttingDownApi() { @@ -110,7 +110,7 @@ void mustShutdownAllProvidersOnShuttingDownApi() { verify(namedProvider).shutdown(); }); - api.resetProviderRepository(); + api.reset(); } } } diff --git a/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java b/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java index f0b78642..c00b8ff2 100644 --- a/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java +++ b/src/test/java/dev/openfeature/sdk/fixtures/ProviderFixture.java @@ -1,24 +1,47 @@ package dev.openfeature.sdk.fixtures; -import dev.openfeature.sdk.FeatureProvider; -import lombok.experimental.UtilityClass; -import org.mockito.stubbing.Answer; +import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doBlock; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import java.io.FileNotFoundException; import java.util.concurrent.CountDownLatch; -import static dev.openfeature.sdk.testutils.stubbing.ConditionStubber.doBlock; -import static org.mockito.Mockito.*; +import org.mockito.stubbing.Answer; + +import dev.openfeature.sdk.FeatureProvider; +import dev.openfeature.sdk.ImmutableContext; +import dev.openfeature.sdk.ProviderState; +import lombok.experimental.UtilityClass; @UtilityClass public class ProviderFixture { public static FeatureProvider createMockedProvider() { - return mock(FeatureProvider.class); + FeatureProvider provider = mock(FeatureProvider.class); + doReturn(ProviderState.NOT_READY).when(provider).getState(); + return provider; + } + + public static FeatureProvider createMockedReadyProvider() { + FeatureProvider provider = mock(FeatureProvider.class); + doReturn(ProviderState.READY).when(provider).getState(); + return provider; + } + + public static FeatureProvider createMockedErrorProvider() throws Exception { + FeatureProvider provider = mock(FeatureProvider.class); + doReturn(ProviderState.NOT_READY).when(provider).getState(); + doThrow(FileNotFoundException.class).when(provider).initialize(any()); + return provider; } - public static FeatureProvider createBlockedProvider(CountDownLatch latch, Runnable onAnswer) { + public static FeatureProvider createBlockedProvider(CountDownLatch latch, Runnable onAnswer) throws Exception { FeatureProvider provider = createMockedProvider(); - doBlock(latch, createAnswerExecutingCode(onAnswer)).when(provider).initialize(); + doBlock(latch, createAnswerExecutingCode(onAnswer)).when(provider).initialize(new ImmutableContext()); doReturn("blockedProvider").when(provider).toString(); return provider; } @@ -30,12 +53,12 @@ private static Answer createAnswerExecutingCode(Runnable onAnswer) { }; } - public static FeatureProvider createUnblockingProvider(CountDownLatch latch) { + public static FeatureProvider createUnblockingProvider(CountDownLatch latch) throws Exception { FeatureProvider provider = createMockedProvider(); doAnswer(invocation -> { latch.countDown(); return null; - }).when(provider).initialize(); + }).when(provider).initialize(new ImmutableContext()); doReturn("unblockingProvider").when(provider).toString(); return provider; } diff --git a/src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java b/src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java new file mode 100644 index 00000000..0c85a7cc --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/internal/TriConsumerTest.java @@ -0,0 +1,34 @@ +package dev.openfeature.sdk.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class TriConsumerTest { + + @Test + @DisplayName("should run accept") + void shouldRunAccept() { + AtomicInteger result = new AtomicInteger(0); + TriConsumer triConsumer = (num1, num2, num3) -> { + result.set(result.get() + num1 + num2 + num3); + }; + triConsumer.accept(1, 2, 3); + assertEquals(6, result.get()); + } + + @Test + @DisplayName("should run after accept") + void shouldRunAfterAccept() { + AtomicInteger result = new AtomicInteger(0); + TriConsumer triConsumer = (num1, num2, num3) -> { + result.set(result.get() + num1 + num2 + num3); + }; + TriConsumer composed = triConsumer.andThen(triConsumer); + composed.accept(1, 2, 3); + assertEquals(12, result.get()); + } +} \ No newline at end of file diff --git a/src/test/java/dev/openfeature/sdk/testutils/TestEventsProvider.java b/src/test/java/dev/openfeature/sdk/testutils/TestEventsProvider.java new file mode 100644 index 00000000..3fcb5888 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/testutils/TestEventsProvider.java @@ -0,0 +1,99 @@ +package dev.openfeature.sdk.testutils; + +import dev.openfeature.sdk.EvaluationContext; +import dev.openfeature.sdk.EventProvider; +import dev.openfeature.sdk.Metadata; +import dev.openfeature.sdk.ProviderEvaluation; +import dev.openfeature.sdk.ProviderEvent; +import dev.openfeature.sdk.ProviderEventDetails; +import dev.openfeature.sdk.ProviderState; +import dev.openfeature.sdk.Value; + +public class TestEventsProvider extends EventProvider { + + private boolean initError = false; + private String initErrorMessage; + private ProviderState state = ProviderState.NOT_READY; + private boolean shutDown = false; + private int initTimeout = 0; + + @Override + public ProviderState getState() { + return this.state; + } + + public TestEventsProvider(int initTimeout) { + this.initTimeout = initTimeout; + } + + public TestEventsProvider(int initTimeout, boolean initError, String initErrorMessage) { + this.initTimeout = initTimeout; + this.initError = initError; + this.initErrorMessage = initErrorMessage; + } + + public TestEventsProvider(ProviderState initialState) { + this.state = initialState; + } + + public void mockEvent(ProviderEvent event, ProviderEventDetails details) { + emit(event, details); + } + + public boolean isShutDown() { + return this.shutDown; + } + + @Override + public void shutdown() { + this.shutDown = true; + } + + @Override + public void initialize(EvaluationContext evaluationContext) throws Exception { + if (ProviderState.NOT_READY.equals(state)) { + // wait half the TIMEOUT, otherwise some init/errors can be fired before we add handlers + Thread.sleep(initTimeout); + if (this.initError) { + this.state = ProviderState.ERROR; + throw new Exception(initErrorMessage); + } + this.state = ProviderState.READY; + } + } + + @Override + public Metadata getMetadata() { + throw new UnsupportedOperationException("Unimplemented method 'getMetadata'"); + } + + @Override + public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, + EvaluationContext ctx) { + throw new UnsupportedOperationException("Unimplemented method 'getBooleanEvaluation'"); + } + + @Override + public ProviderEvaluation getStringEvaluation(String key, String defaultValue, + EvaluationContext ctx) { + throw new UnsupportedOperationException("Unimplemented method 'getStringEvaluation'"); + } + + @Override + public ProviderEvaluation getIntegerEvaluation(String key, Integer defaultValue, + EvaluationContext ctx) { + throw new UnsupportedOperationException("Unimplemented method 'getIntegerEvaluation'"); + } + + @Override + public ProviderEvaluation getDoubleEvaluation(String key, Double defaultValue, + EvaluationContext ctx) { + throw new UnsupportedOperationException("Unimplemented method 'getDoubleEvaluation'"); + } + + @Override + public ProviderEvaluation getObjectEvaluation(String key, Value defaultValue, + EvaluationContext ctx) { + throw new UnsupportedOperationException("Unimplemented method 'getObjectEvaluation'"); + } +}; \ No newline at end of file From 40d1f0a1d52ca09df2a0e6a5d39604fb8162a4f7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:01:15 +0000 Subject: [PATCH 132/134] chore(deps): update github/codeql-action digest to c552617 (#506) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- .github/workflows/static-code-scanning.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 5a1b2d35..f3db5d6a 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Initialize CodeQL - uses: github/codeql-action/init@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 + uses: github/codeql-action/init@c5526174a564f5a5444d71884af87163f19cf394 with: languages: java @@ -51,4 +51,4 @@ jobs: verbose: true # optional (default = false) - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 + uses: github/codeql-action/analyze@c5526174a564f5a5444d71884af87163f19cf394 diff --git a/.github/workflows/static-code-scanning.yaml b/.github/workflows/static-code-scanning.yaml index dbbba159..ffcf6db1 100644 --- a/.github/workflows/static-code-scanning.yaml +++ b/.github/workflows/static-code-scanning.yaml @@ -33,12 +33,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 + uses: github/codeql-action/init@c5526174a564f5a5444d71884af87163f19cf394 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 + uses: github/codeql-action/autobuild@c5526174a564f5a5444d71884af87163f19cf394 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@12aa0a6e0191c2100e62e485c1ff0670e7cf0f35 + uses: github/codeql-action/analyze@c5526174a564f5a5444d71884af87163f19cf394 From c115e96ae67ce7d006d8ee495685d07895c06774 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Thu, 13 Jul 2023 15:49:39 -0400 Subject: [PATCH 133/134] chore: update readme for events (#507) Signed-off-by: Todd Baert --- README.md | 105 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 473d9350..2d2d79bd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@

OpenFeature Java SDK

-[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.5.2&color=yellow)](https://github.com/open-feature/spec/tree/v0.5.2) +[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.6.0&color=yellow)](https://github.com/open-feature/spec/tree/v0.6.0) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.openfeature/sdk) [![javadoc](https://javadoc.io/badge2/dev.openfeature/sdk/javadoc.svg)](https://javadoc.io/doc/dev.openfeature/sdk) [![Project Status: Active โ€“ The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) @@ -28,13 +28,13 @@ Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition. -## ๐Ÿ” Requirements: +## ๐Ÿ” Requirements - Java 8+ (compiler target is 1.8) Note that this library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices. -## ๐Ÿ“ฆ Installation: +## ๐Ÿ“ฆ Installation ### Maven @@ -76,16 +76,14 @@ dependencies { We publish SBOMs with all of our releases as of 0.3.0. You can find them in Maven Central alongside the artifacts. -## ๐ŸŒŸ Features: +## ๐ŸŒŸ Features - support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider) - easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks) - bool, string, numeric, and object flag types - [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation -## ๐Ÿš€ Usage: - -### Basics: +## ๐Ÿš€ Usage ```java public void example(){ @@ -102,7 +100,7 @@ public void example(){ } ``` -### Context-aware evaluation: +### Context-aware evaluation Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting). @@ -127,9 +125,73 @@ EvaluationContext reqCtx = new ImmutableContext(targetingKey, attributes); boolean flagValue = client.getBooleanValue("some-flag", false, reqCtx); ``` +### Events + +Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. +Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider. +Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`. +Please refer to the documentation of the provider you're using to see what events are supported. + +```java +// add an event handler to a client +client.onProviderConfigurationChanged((EventDetails eventDetails) -> { + // do something when the provider's flag settings change +}); + +// add an event handler to the global API +OpenFeatureAPI.getInstance().onProviderStale((EventDetails eventDetails) -> { + // do something when the provider's cache goes stale +}); +``` + +### Hooks + +A hook is a mechanism that allows for adding arbitrary behavior at well-defined points of the flag evaluation life-cycle. +Use cases include validating the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. + +```java +public class MyHook implements Hook { + /** + * + * @param ctx Information about the particular flag evaluation + * @param details Information about how the flag was resolved, including any resolved values. + * @param hints An immutable mapping of data for users to communicate to the hooks. + */ + @Override + public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) { + System.out.println("After evaluation!"); + } +} +``` + +See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available hooks. + +### Logging: + +The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation. + +### Named clients + +Clients can be given a name. +A name is a logical identifier which can be used to associate clients with a particular provider. +If a name has no associated provider, clients with that name use the global provider. + +```java +FeatureProvider scopedProvider = new MyProvider(); + +// set this provider for clients named "my-name" +OpenFeatureAPI.getInstance().setProvider("my-name", provider); + +// create a client bound to the provider above +Client client = OpenFeatureAPI.getInstance().getClient("my-name"); +``` + ### Providers: -To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/java-sdk-contrib) available under the OpenFeature organization. Finally, youโ€™ll then need to write the provider itself. This can be accomplished by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. +To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. +This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/java-sdk-contrib) available under the OpenFeature organization. +Finally, youโ€™ll then need to write the provider itself. +This can be accomplished by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. ```java public class MyProvider implements FeatureProvider { @@ -167,31 +229,16 @@ public class MyProvider implements FeatureProvider { See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available providers. -### Hooks: +### Shutdown -A hook is a mechanism that allows for adding arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validating the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. +The OpenFeature API provides a close function to perform a cleanup of all registered providers. +This should only be called when your application is in the process of shutting down. ```java -public class MyHook implements Hook { - /** - * - * @param ctx Information about the particular flag evaluation - * @param details Information about how the flag was resolved, including any resolved values. - * @param hints An immutable mapping of data for users to communicate to the hooks. - */ - @Override - public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) { - System.out.println("After evaluation!"); - } -} +// shut down all providers +OpenFeatureAPI.getInstance().shutdown(); ``` -See [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Java) for a catalog of available hooks. - -### Logging: - -The Java SDK uses SLF4J. See the [SLF4J manual](https://slf4j.org/manual.html) for complete documentation. - ### Complete API documentation: See [here](https://www.javadoc.io/doc/dev.openfeature/sdk/latest/index.html) for the complete API documentation. From 9a3a07f774805b6c72a14535086e571d3eb1a87e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:52:03 -0400 Subject: [PATCH 134/134] chore(main): release 1.4.0 (#364) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 145 ++++++++++++++++++++++++++++++++++ README.md | 4 +- pom.xml | 2 +- version.txt | 2 +- 5 files changed, 150 insertions(+), 5 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 00d9fffc..802de1e8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"1.3.1"} \ No newline at end of file +{".":"1.4.0"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e59bc30f..3b72181f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,150 @@ # Changelog +## [1.4.0](https://github.com/open-feature/java-sdk/compare/v1.3.1...v1.4.0) (2023-07-13) + + +### ๐Ÿ› Bug Fixes + +* **deps:** update dependency io.cucumber:cucumber-bom to v7.12.0 ([#413](https://github.com/open-feature/java-sdk/issues/413)) ([f0f5d28](https://github.com/open-feature/java-sdk/commit/f0f5d284169081cae8fc88cffa04d17ac776a51f)) +* **deps:** update dependency io.cucumber:cucumber-bom to v7.12.1 ([#461](https://github.com/open-feature/java-sdk/issues/461)) ([c26b755](https://github.com/open-feature/java-sdk/commit/c26b75593edaf3a6f87c85bb9065ec485612c723)) +* **deps:** update dependency io.cucumber:cucumber-bom to v7.13.0 ([#499](https://github.com/open-feature/java-sdk/issues/499)) ([da00304](https://github.com/open-feature/java-sdk/commit/da0030408307b580fd912f5bf390b599f7a79024)) +* **deps:** update dependency org.projectlombok:lombok to v1.18.28 ([#448](https://github.com/open-feature/java-sdk/issues/448)) ([dfb214c](https://github.com/open-feature/java-sdk/commit/dfb214c52f89a84becd170925721179a2ff24c75)) +* **deps:** update junit5 monorepo ([#410](https://github.com/open-feature/java-sdk/issues/410)) ([854d0be](https://github.com/open-feature/java-sdk/commit/854d0be0f473c212884163680e2ee5df5eded0c6)) + + +### โœจ New Features + +* add empty constructors to data classes ([#491](https://github.com/open-feature/java-sdk/issues/491)) ([693721e](https://github.com/open-feature/java-sdk/commit/693721e36c5b31adacd96afc55bc38ed53534db4)) +* add flag metadata ([#459](https://github.com/open-feature/java-sdk/issues/459)) ([3ed40a3](https://github.com/open-feature/java-sdk/commit/3ed40a388797dc6939bff5d06e7c4528773df791)) +* add initialize and shutdown behavior ([#456](https://github.com/open-feature/java-sdk/issues/456)) ([5f173ff](https://github.com/open-feature/java-sdk/commit/5f173ff8607e8430bf14a57e7782dc0e8460317a)) +* events ([#476](https://github.com/open-feature/java-sdk/issues/476)) ([bad5b0a](https://github.com/open-feature/java-sdk/commit/bad5b0a7f5167d0b57bf502ce86b32b1c538746c)) +* Support mapping a client to a given provider. ([#388](https://github.com/open-feature/java-sdk/issues/388)) ([d4c43d7](https://github.com/open-feature/java-sdk/commit/d4c43d74bc37371fc19dc1983e96e7c904d5a1e7)) + + +### ๐Ÿงน Chore + +* **deps:** update actions/cache digest to 67b839e ([#473](https://github.com/open-feature/java-sdk/issues/473)) ([6d456ca](https://github.com/open-feature/java-sdk/commit/6d456ca618ba78eadcfe00bd63383b9f7dba32b0)) +* **deps:** update actions/checkout digest to 47fbe2d ([#393](https://github.com/open-feature/java-sdk/issues/393)) ([43a75d0](https://github.com/open-feature/java-sdk/commit/43a75d080c3594669fe6c594b2818ee9fe22955e)) +* **deps:** update actions/checkout digest to 83b7061 ([#389](https://github.com/open-feature/java-sdk/issues/389)) ([f3e65db](https://github.com/open-feature/java-sdk/commit/f3e65db54e24926f529e939b5a27f605c46f3185)) +* **deps:** update actions/checkout digest to 8e5e7e5 ([#391](https://github.com/open-feature/java-sdk/issues/391)) ([9c98e83](https://github.com/open-feature/java-sdk/commit/9c98e83ed6a1a471b6c5488b8c87681fd92dd77d)) +* **deps:** update actions/checkout digest to 96f5310 ([#471](https://github.com/open-feature/java-sdk/issues/471)) ([fe42073](https://github.com/open-feature/java-sdk/commit/fe420733850018b1d579601a1d3b4149a93605d6)) +* **deps:** update actions/checkout digest to f095bcc ([#398](https://github.com/open-feature/java-sdk/issues/398)) ([3015571](https://github.com/open-feature/java-sdk/commit/30155712bc35a070febc5761b1ad03dc25183a26)) +* **deps:** update actions/setup-java digest to 191ba8c ([#375](https://github.com/open-feature/java-sdk/issues/375)) ([bdb08d7](https://github.com/open-feature/java-sdk/commit/bdb08d7af809bfb4593cf38830b843fb433a95ae)) +* **deps:** update actions/setup-java digest to 1f2faad ([#484](https://github.com/open-feature/java-sdk/issues/484)) ([c3528da](https://github.com/open-feature/java-sdk/commit/c3528da7024fa585ce265a620bca1f936ec508c1)) +* **deps:** update actions/setup-java digest to 45058d7 ([#479](https://github.com/open-feature/java-sdk/issues/479)) ([ec6d44a](https://github.com/open-feature/java-sdk/commit/ec6d44ae8969f73098fac8e98830800486b73a9a)) +* **deps:** update actions/setup-java digest to 75c6561 ([#503](https://github.com/open-feature/java-sdk/issues/503)) ([2d3b644](https://github.com/open-feature/java-sdk/commit/2d3b6448963e794242babe016597fb5aa198afaf)) +* **deps:** update actions/setup-java digest to 87c1c70 ([#469](https://github.com/open-feature/java-sdk/issues/469)) ([89cedb9](https://github.com/open-feature/java-sdk/commit/89cedb9d2ec709d7ad218e8b94852f8b947eb7f6)) +* **deps:** update actions/setup-java digest to ddb82ce ([#381](https://github.com/open-feature/java-sdk/issues/381)) ([a737c3a](https://github.com/open-feature/java-sdk/commit/a737c3a36bb5899c7e4b1efab69a3d4f13f24325)) +* **deps:** update actions/setup-java digest to e42168c ([#371](https://github.com/open-feature/java-sdk/issues/371)) ([0ce5b43](https://github.com/open-feature/java-sdk/commit/0ce5b43a81d5334460e8724f55798486bc9813d0)) +* **deps:** update amannn/action-semantic-pull-request digest to 00282d6 ([#490](https://github.com/open-feature/java-sdk/issues/490)) ([8b9e050](https://github.com/open-feature/java-sdk/commit/8b9e0500924475bccd3f069f5967b5af59d50f12)) +* **deps:** update amannn/action-semantic-pull-request digest to 3bb5af3 ([#435](https://github.com/open-feature/java-sdk/issues/435)) ([88e7d60](https://github.com/open-feature/java-sdk/commit/88e7d6054f60c15dc6f1130c4b6fe77be7098a5d)) +* **deps:** update codecov/codecov-action digest to 1dd0ce3 ([#414](https://github.com/open-feature/java-sdk/issues/414)) ([9d7d3d4](https://github.com/open-feature/java-sdk/commit/9d7d3d41f6a8e75b9a2b02e755a4c4048a3bc611)) +* **deps:** update codecov/codecov-action digest to 40a12dc ([#385](https://github.com/open-feature/java-sdk/issues/385)) ([5072553](https://github.com/open-feature/java-sdk/commit/507255316614cef8653c833d7c83322f999485ef)) +* **deps:** update codecov/codecov-action digest to 49c20db ([#431](https://github.com/open-feature/java-sdk/issues/431)) ([106df46](https://github.com/open-feature/java-sdk/commit/106df4661dd8e46da698ea4c90e8447aa958e6b7)) +* **deps:** update codecov/codecov-action digest to 5bf2504 ([#418](https://github.com/open-feature/java-sdk/issues/418)) ([19415ed](https://github.com/open-feature/java-sdk/commit/19415edb713533d606b6483fb8fdfea4b838b133)) +* **deps:** update codecov/codecov-action digest to 6757614 ([#400](https://github.com/open-feature/java-sdk/issues/400)) ([427d5a6](https://github.com/open-feature/java-sdk/commit/427d5a627251061651040e841d5e4db582f03cd4)) +* **deps:** update codecov/codecov-action digest to 894ff02 ([#402](https://github.com/open-feature/java-sdk/issues/402)) ([212590e](https://github.com/open-feature/java-sdk/commit/212590e5e26317a4e70caca4d201e21cb7ffa7b4)) +* **deps:** update codecov/codecov-action digest to 91e1847 ([#372](https://github.com/open-feature/java-sdk/issues/372)) ([dfa08b9](https://github.com/open-feature/java-sdk/commit/dfa08b90e1cf3f698f9058f95e7e41567a1934bb)) +* **deps:** update codecov/codecov-action digest to b4dfea7 ([#419](https://github.com/open-feature/java-sdk/issues/419)) ([b7dd2fc](https://github.com/open-feature/java-sdk/commit/b7dd2fc5a2ad9d00fb6500b1647ffb70dd539b45)) +* **deps:** update codecov/codecov-action digest to cf8e3e4 ([#428](https://github.com/open-feature/java-sdk/issues/428)) ([59d8a10](https://github.com/open-feature/java-sdk/commit/59d8a10ba311f7808a02db2773bad64356dda8e3)) +* **deps:** update codecov/codecov-action digest to eaaf4be ([#433](https://github.com/open-feature/java-sdk/issues/433)) ([3ff9995](https://github.com/open-feature/java-sdk/commit/3ff9995a437508ebb227c24e1c731dee447fc092)) +* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.7.3.4 ([#380](https://github.com/open-feature/java-sdk/issues/380)) ([ec3111f](https://github.com/open-feature/java-sdk/commit/ec3111f5d7fb12343a45ff70296238cf747554ef)) +* **deps:** update dependency com.github.spotbugs:spotbugs-maven-plugin to v4.7.3.5 ([#482](https://github.com/open-feature/java-sdk/issues/482)) ([b8b927e](https://github.com/open-feature/java-sdk/commit/b8b927ef4a418c32effb9fbc644667ec48a4ce7e)) +* **deps:** update dependency com.google.guava:guava to v32 ([#455](https://github.com/open-feature/java-sdk/issues/455)) ([5888aea](https://github.com/open-feature/java-sdk/commit/5888aead97a70495b8fd9489aa1a8b23ea2f365e)) +* **deps:** update dependency com.google.guava:guava to v32.0.1-jre ([#470](https://github.com/open-feature/java-sdk/issues/470)) ([3946211](https://github.com/open-feature/java-sdk/commit/3946211c5d042f17a04d6941430462f70b27a7d2)) +* **deps:** update dependency com.google.guava:guava to v32.1.0-jre ([#492](https://github.com/open-feature/java-sdk/issues/492)) ([207a221](https://github.com/open-feature/java-sdk/commit/207a221d4674c8cda7881ee41c1515048a0a059e)) +* **deps:** update dependency com.google.guava:guava to v32.1.1-jre ([#494](https://github.com/open-feature/java-sdk/issues/494)) ([a7c7d42](https://github.com/open-feature/java-sdk/commit/a7c7d4287960d6825a57d14d9878032d2d2170d0)) +* **deps:** update dependency dev.openfeature.contrib.providers:flagd to v0.5.10 ([#429](https://github.com/open-feature/java-sdk/issues/429)) ([5388fa1](https://github.com/open-feature/java-sdk/commit/5388fa12b61d127588aca02999d26bc3c9986b1c)) +* **deps:** update dependency dev.openfeature.contrib.providers:flagd to v0.5.8 ([#360](https://github.com/open-feature/java-sdk/issues/360)) ([de9a928](https://github.com/open-feature/java-sdk/commit/de9a928f93679295ad9244b7dc6def1af1d9f7fc)) +* **deps:** update dependency dev.openfeature.contrib.providers:flagd to v0.5.9 ([#416](https://github.com/open-feature/java-sdk/issues/416)) ([434da5a](https://github.com/open-feature/java-sdk/commit/434da5a6080a8c3827a9a9cbb08ed98107c14264)) +* **deps:** update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.2.2 ([#403](https://github.com/open-feature/java-sdk/issues/403)) ([311b73f](https://github.com/open-feature/java-sdk/commit/311b73fe353ea723f2aa8df70b7ec92e91b8d0f8)) +* **deps:** update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.3.0 ([#444](https://github.com/open-feature/java-sdk/issues/444)) ([f9523ec](https://github.com/open-feature/java-sdk/commit/f9523ecd8b4585619ea6e12caffcb90c42eb354c)) +* **deps:** update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.6.0 ([#445](https://github.com/open-feature/java-sdk/issues/445)) ([eb6f9e6](https://github.com/open-feature/java-sdk/commit/eb6f9e69ef8729d2850f8c1e63a66f30c0a8dd51)) +* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.1.0 ([#425](https://github.com/open-feature/java-sdk/issues/425)) ([839fddb](https://github.com/open-feature/java-sdk/commit/839fddb927575d92ed114518d9f2c16a92a0994b)) +* **deps:** update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.1.2 ([#464](https://github.com/open-feature/java-sdk/issues/464)) ([24f0923](https://github.com/open-feature/java-sdk/commit/24f092319dfade89b2a6a62b86cce2d88b81fa3a)) +* **deps:** update dependency org.apache.maven.plugins:maven-gpg-plugin to v3.1.0 ([#423](https://github.com/open-feature/java-sdk/issues/423)) ([64f79cd](https://github.com/open-feature/java-sdk/commit/64f79cd513c698656eed2b10903b60ef3891c141)) +* **deps:** update dependency org.apache.maven.plugins:maven-pmd-plugin to v3.21.0 ([#434](https://github.com/open-feature/java-sdk/issues/434)) ([4d65590](https://github.com/open-feature/java-sdk/commit/4d655900d94351de8700120acb90d4429e15a136)) +* **deps:** update dependency org.apache.maven.plugins:maven-source-plugin to v3.3.0 ([#443](https://github.com/open-feature/java-sdk/issues/443)) ([bcbaff8](https://github.com/open-feature/java-sdk/commit/bcbaff8e4f15122d7e083ce68af7c0446adaf9fa)) +* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.1.0 ([#426](https://github.com/open-feature/java-sdk/issues/426)) ([0ccf337](https://github.com/open-feature/java-sdk/commit/0ccf337384a3ffd286560ad29a3f4531998e8e2b)) +* **deps:** update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.1.2 ([#465](https://github.com/open-feature/java-sdk/issues/465)) ([6107e91](https://github.com/open-feature/java-sdk/commit/6107e91be4eef92e5dfa96e6b7b862d7e3a85df1)) +* **deps:** update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 ([#432](https://github.com/open-feature/java-sdk/issues/432)) ([aa495b2](https://github.com/open-feature/java-sdk/commit/aa495b28470d9a75bd64c148260b352dd8e6c6c2)) +* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.6 ([#370](https://github.com/open-feature/java-sdk/issues/370)) ([d7b3ca0](https://github.com/open-feature/java-sdk/commit/d7b3ca0513f80e933d25d6ada2ef3cbbbf961b38)) +* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.7 ([#396](https://github.com/open-feature/java-sdk/issues/396)) ([a5eaf79](https://github.com/open-feature/java-sdk/commit/a5eaf79cf9d039ab5319d8c4101b0fd8c395166e)) +* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.8 ([#408](https://github.com/open-feature/java-sdk/issues/408)) ([c426e66](https://github.com/open-feature/java-sdk/commit/c426e6646f55e6575f0e1c044e4aa2a8efc2e0c0)) +* **deps:** update dependency org.cyclonedx:cyclonedx-maven-plugin to v2.7.9 ([#438](https://github.com/open-feature/java-sdk/issues/438)) ([c3e82e9](https://github.com/open-feature/java-sdk/commit/c3e82e97ddf071916b9c9e287bc935f5d177d01d)) +* **deps:** update dependency org.jacoco:jacoco-maven-plugin to v0.8.10 ([#407](https://github.com/open-feature/java-sdk/issues/407)) ([5b10d39](https://github.com/open-feature/java-sdk/commit/5b10d399cb2fdf38fe46105d53fa2ae36eb2e0b2)) +* **deps:** update dependency org.jacoco:jacoco-maven-plugin to v0.8.9 ([#374](https://github.com/open-feature/java-sdk/issues/374)) ([ade4878](https://github.com/open-feature/java-sdk/commit/ade4878abc1efd993f2dc2977adbc0cc45b84be2)) +* **deps:** update github/codeql-action digest to 0ac1815 ([#477](https://github.com/open-feature/java-sdk/issues/477)) ([3501425](https://github.com/open-feature/java-sdk/commit/3501425f48feef82a50161ed072a68bae97053c9)) +* **deps:** update github/codeql-action digest to 11ea309 ([#447](https://github.com/open-feature/java-sdk/issues/447)) ([8d675ca](https://github.com/open-feature/java-sdk/commit/8d675ca38751e9c7bb8c7dd74591b9992cb696ec)) +* **deps:** update github/codeql-action digest to 1245696 ([#446](https://github.com/open-feature/java-sdk/issues/446)) ([e393b64](https://github.com/open-feature/java-sdk/commit/e393b64715f27cd96a1823c537c6d4c58030e0a2)) +* **deps:** update github/codeql-action digest to 12aa0a6 ([#505](https://github.com/open-feature/java-sdk/issues/505)) ([893d0da](https://github.com/open-feature/java-sdk/commit/893d0da6126ce49c73a90d20094a2e0123300ebb)) +* **deps:** update github/codeql-action digest to 130884e ([#430](https://github.com/open-feature/java-sdk/issues/430)) ([6405100](https://github.com/open-feature/java-sdk/commit/6405100b275f6465bbdcd25b5158ff6aad386f8b)) +* **deps:** update github/codeql-action digest to 1e1aca8 ([#421](https://github.com/open-feature/java-sdk/issues/421)) ([7aade9a](https://github.com/open-feature/java-sdk/commit/7aade9a875245ededdb56597a89f4745f0d58622)) +* **deps:** update github/codeql-action digest to 2d031a3 ([#451](https://github.com/open-feature/java-sdk/issues/451)) ([fa1e144](https://github.com/open-feature/java-sdk/commit/fa1e14451d04663dabc314e25e6ddf5ba1fb2ecf)) +* **deps:** update github/codeql-action digest to 318bcc7 ([#420](https://github.com/open-feature/java-sdk/issues/420)) ([42b9317](https://github.com/open-feature/java-sdk/commit/42b931776a559fcc35ddee442d60bce6e86b16dd)) +* **deps:** update github/codeql-action digest to 46a6823 ([#493](https://github.com/open-feature/java-sdk/issues/493)) ([331d511](https://github.com/open-feature/java-sdk/commit/331d5110dab6e4806a5a45301d2f16c86d764644)) +* **deps:** update github/codeql-action digest to 5f061ca ([#450](https://github.com/open-feature/java-sdk/issues/450)) ([79222e1](https://github.com/open-feature/java-sdk/commit/79222e1cf7223ceee75f587804904492ca004b74)) +* **deps:** update github/codeql-action digest to 66aeadb ([#377](https://github.com/open-feature/java-sdk/issues/377)) ([5c335d4](https://github.com/open-feature/java-sdk/commit/5c335d45393227cdeb3813630ee6ef9d4196916d)) +* **deps:** update github/codeql-action digest to 6a07b2a ([#502](https://github.com/open-feature/java-sdk/issues/502)) ([b0201c7](https://github.com/open-feature/java-sdk/commit/b0201c7d4311f4c4ababa91984cf937b48ec7d35)) +* **deps:** update github/codeql-action digest to 6bd8101 ([#454](https://github.com/open-feature/java-sdk/issues/454)) ([cc155b3](https://github.com/open-feature/java-sdk/commit/cc155b354c4978274d386eb769260f02535bc198)) +* **deps:** update github/codeql-action digest to 6cfb483 ([#439](https://github.com/open-feature/java-sdk/issues/439)) ([1af8e96](https://github.com/open-feature/java-sdk/commit/1af8e966a461d2eff40fdd3749df09e849339134)) +* **deps:** update github/codeql-action digest to 84c0579 ([#498](https://github.com/open-feature/java-sdk/issues/498)) ([10bee74](https://github.com/open-feature/java-sdk/commit/10bee74d16bba1bcaa110d58160e0f4eb9e7a960)) +* **deps:** update github/codeql-action digest to 85c77f1 ([#500](https://github.com/open-feature/java-sdk/issues/500)) ([4f6d7ff](https://github.com/open-feature/java-sdk/commit/4f6d7ff46d931c5f8bbdd454dda7c9b2c09578e8)) +* **deps:** update github/codeql-action digest to 8b0f2cf ([#462](https://github.com/open-feature/java-sdk/issues/462)) ([7f91942](https://github.com/open-feature/java-sdk/commit/7f9194231c6340a712a23b7298772fba3b4f4824)) +* **deps:** update github/codeql-action digest to 8ba77ef ([#485](https://github.com/open-feature/java-sdk/issues/485)) ([dac79f0](https://github.com/open-feature/java-sdk/commit/dac79f0bd5f856230a86b7bc3e3842db92a5f8b6)) +* **deps:** update github/codeql-action digest to 8ca5570 ([#415](https://github.com/open-feature/java-sdk/issues/415)) ([0de764d](https://github.com/open-feature/java-sdk/commit/0de764db19e793b81eeea345bcec8be6bc83b2b6)) +* **deps:** update github/codeql-action digest to 926a489 ([#460](https://github.com/open-feature/java-sdk/issues/460)) ([0b1315e](https://github.com/open-feature/java-sdk/commit/0b1315eaaf4cb36bfb6c45a31d337e3ae31c0ea5)) +* **deps:** update github/codeql-action digest to 95a5fda ([#504](https://github.com/open-feature/java-sdk/issues/504)) ([00c8120](https://github.com/open-feature/java-sdk/commit/00c812045926e627743ec5ff699acf6ea6797f8f)) +* **deps:** update github/codeql-action digest to 95cfca7 ([#427](https://github.com/open-feature/java-sdk/issues/427)) ([20628a2](https://github.com/open-feature/java-sdk/commit/20628a23054768238cdef503382ee6b3c6d34476)) +* **deps:** update github/codeql-action digest to 96f2840 ([#458](https://github.com/open-feature/java-sdk/issues/458)) ([401d7a8](https://github.com/open-feature/java-sdk/commit/401d7a8a5fe19835710eadce3fa88a2fcb0ee5c9)) +* **deps:** update github/codeql-action digest to 988e1bc ([#379](https://github.com/open-feature/java-sdk/issues/379)) ([9b77827](https://github.com/open-feature/java-sdk/commit/9b778277968851752bd569a09f6609f2cb3ffe48)) +* **deps:** update github/codeql-action digest to 98f7bbd ([#383](https://github.com/open-feature/java-sdk/issues/383)) ([037d611](https://github.com/open-feature/java-sdk/commit/037d61128e1e8a06a16d5ac899c2c92762baa4b3)) +* **deps:** update github/codeql-action digest to 9a866ed ([#395](https://github.com/open-feature/java-sdk/issues/395)) ([2ff65b8](https://github.com/open-feature/java-sdk/commit/2ff65b8344d0a3ffe6daebc3fb9b40ade21e2d7e)) +* **deps:** update github/codeql-action digest to 9d2dd7c ([#457](https://github.com/open-feature/java-sdk/issues/457)) ([e1a0432](https://github.com/open-feature/java-sdk/commit/e1a0432ae988c5311bc00008fd3e8687d3a3839f)) +* **deps:** update github/codeql-action digest to a2d725d ([#497](https://github.com/open-feature/java-sdk/issues/497)) ([2f028f6](https://github.com/open-feature/java-sdk/commit/2f028f699012fb160f156249ef9c85ecd8c2df13)) +* **deps:** update github/codeql-action digest to a42c0ca ([#496](https://github.com/open-feature/java-sdk/issues/496)) ([9ddc9f1](https://github.com/open-feature/java-sdk/commit/9ddc9f1cb2c85c2d096a493342e429120ff36e92)) +* **deps:** update github/codeql-action digest to a8affb0 ([#401](https://github.com/open-feature/java-sdk/issues/401)) ([c92cd2c](https://github.com/open-feature/java-sdk/commit/c92cd2ccfeb028a43637a545e56142305f76c833)) +* **deps:** update github/codeql-action digest to a9648ea ([#405](https://github.com/open-feature/java-sdk/issues/405)) ([a5f076b](https://github.com/open-feature/java-sdk/commit/a5f076b37c0cba94cc7ae22577abdba43ee011ea)) +* **deps:** update github/codeql-action digest to afdf30f ([#397](https://github.com/open-feature/java-sdk/issues/397)) ([b55ed6c](https://github.com/open-feature/java-sdk/commit/b55ed6cf7417f248b44d9ca86535deee7c80cfcc)) +* **deps:** update github/codeql-action digest to b8f204c ([#474](https://github.com/open-feature/java-sdk/issues/474)) ([d309d16](https://github.com/open-feature/java-sdk/commit/d309d1633018217e1c2fad8bff8f3b55706aa016)) +* **deps:** update github/codeql-action digest to bb28e7e ([#368](https://github.com/open-feature/java-sdk/issues/368)) ([5e648f6](https://github.com/open-feature/java-sdk/commit/5e648f6332f08c72a5e232bd6ae2171e6476a05e)) +* **deps:** update github/codeql-action digest to bcb460d ([#495](https://github.com/open-feature/java-sdk/issues/495)) ([a8e3410](https://github.com/open-feature/java-sdk/commit/a8e34100a02fdd102a605030b5be47796258ec23)) +* **deps:** update github/codeql-action digest to be2b53b ([#394](https://github.com/open-feature/java-sdk/issues/394)) ([28e191d](https://github.com/open-feature/java-sdk/commit/28e191d4231c6c04971724e3d88166260a96bef4)) +* **deps:** update github/codeql-action digest to c552617 ([#506](https://github.com/open-feature/java-sdk/issues/506)) ([40d1f0a](https://github.com/open-feature/java-sdk/commit/40d1f0a1d52ca09df2a0e6a5d39604fb8162a4f7)) +* **deps:** update github/codeql-action digest to c5f3f01 ([#404](https://github.com/open-feature/java-sdk/issues/404)) ([6898514](https://github.com/open-feature/java-sdk/commit/6898514fca1f4c97edd1453217b4b6d70d996803)) +* **deps:** update github/codeql-action digest to c6dff34 ([#481](https://github.com/open-feature/java-sdk/issues/481)) ([ea54bff](https://github.com/open-feature/java-sdk/commit/ea54bff9cc6a452fd6e329d0c3f2bad678e498a5)) +* **deps:** update github/codeql-action digest to ca6b925 ([#436](https://github.com/open-feature/java-sdk/issues/436)) ([468c42d](https://github.com/open-feature/java-sdk/commit/468c42d4e3902085cda852901097b5c197fd7906)) +* **deps:** update github/codeql-action digest to cdcdbb5 ([#463](https://github.com/open-feature/java-sdk/issues/463)) ([736cf24](https://github.com/open-feature/java-sdk/commit/736cf24cbf54680c7c9ce66b05ef74402743f899)) +* **deps:** update github/codeql-action digest to cff3d9e ([#486](https://github.com/open-feature/java-sdk/issues/486)) ([6cd588b](https://github.com/open-feature/java-sdk/commit/6cd588b87a091ba11ccf3db8b2f72ffffbde358b)) +* **deps:** update github/codeql-action digest to d944b34 ([#390](https://github.com/open-feature/java-sdk/issues/390)) ([519c32a](https://github.com/open-feature/java-sdk/commit/519c32a087e94376b9a245ad9c1a4fab360adfe2)) +* **deps:** update github/codeql-action digest to da583b0 ([#409](https://github.com/open-feature/java-sdk/issues/409)) ([5abe971](https://github.com/open-feature/java-sdk/commit/5abe971bdba796cfb435ee02e72179ae406a05f0)) +* **deps:** update github/codeql-action digest to dc04638 ([#392](https://github.com/open-feature/java-sdk/issues/392)) ([813c7e2](https://github.com/open-feature/java-sdk/commit/813c7e21ab933680f507dc077ceabbdbda9299e0)) +* **deps:** update github/codeql-action digest to dc81ae3 ([#367](https://github.com/open-feature/java-sdk/issues/367)) ([bac2af3](https://github.com/open-feature/java-sdk/commit/bac2af3033245db5bb5da18790f86e657a773686)) +* **deps:** update github/codeql-action digest to dcf71cf ([#411](https://github.com/open-feature/java-sdk/issues/411)) ([2df3205](https://github.com/open-feature/java-sdk/commit/2df3205c747a8f156e38f8510d3f95f49527f6a8)) +* **deps:** update github/codeql-action digest to de74ca6 ([#480](https://github.com/open-feature/java-sdk/issues/480)) ([bd3042b](https://github.com/open-feature/java-sdk/commit/bd3042ba0d15e0bd9a2f0d68693633adb555f6e2)) +* **deps:** update github/codeql-action digest to deb312c ([#422](https://github.com/open-feature/java-sdk/issues/422)) ([af3e3d6](https://github.com/open-feature/java-sdk/commit/af3e3d60dc12f37199e79a0f6dd5f7b065944a49)) +* **deps:** update github/codeql-action digest to e287d85 ([#472](https://github.com/open-feature/java-sdk/issues/472)) ([fa94c0e](https://github.com/open-feature/java-sdk/commit/fa94c0e0ddbcb0bf5e6af7d1b6f53c1b885d7270)) +* **deps:** update github/codeql-action digest to ed6c499 ([#386](https://github.com/open-feature/java-sdk/issues/386)) ([f1ecfac](https://github.com/open-feature/java-sdk/commit/f1ecfac6aaac1102bd380a25935a42c64eda441b)) +* **deps:** update github/codeql-action digest to f0a422f ([#373](https://github.com/open-feature/java-sdk/issues/373)) ([6a8c911](https://github.com/open-feature/java-sdk/commit/6a8c911287d8b3d2e35f6455af3496a532a71553)) +* **deps:** update github/codeql-action digest to f31a31c ([#412](https://github.com/open-feature/java-sdk/issues/412)) ([be9d652](https://github.com/open-feature/java-sdk/commit/be9d6523ff0cb3d42e68d8f4d36fe9661ec25eca)) +* **deps:** update github/codeql-action digest to f32426b ([#378](https://github.com/open-feature/java-sdk/issues/378)) ([ae30789](https://github.com/open-feature/java-sdk/commit/ae307892a5fbc9ac02db47e42acc1a723b714938)) +* **deps:** update github/codeql-action digest to f8b1cb6 ([#453](https://github.com/open-feature/java-sdk/issues/453)) ([1dddd68](https://github.com/open-feature/java-sdk/commit/1dddd68c4243a8823bb1b92091d3b25871e50ed8)) +* **deps:** update github/codeql-action digest to fa7cce4 ([#376](https://github.com/open-feature/java-sdk/issues/376)) ([23c4c4c](https://github.com/open-feature/java-sdk/commit/23c4c4cef9ff0d18aec44af5c0c808439124d142)) +* **deps:** update github/codeql-action digest to fff3a80 ([#365](https://github.com/open-feature/java-sdk/issues/365)) ([3ae2a54](https://github.com/open-feature/java-sdk/commit/3ae2a541a1c8a9fc568a97aa02301df1353e092b)) +* **deps:** update google-github-actions/release-please-action digest to 01f98cb ([#489](https://github.com/open-feature/java-sdk/issues/489)) ([7f01ded](https://github.com/open-feature/java-sdk/commit/7f01deda5b5fb20ca126019e8553c4ac10ce460f)) +* **deps:** update google-github-actions/release-please-action digest to 51ee8ae ([#452](https://github.com/open-feature/java-sdk/issues/452)) ([58df782](https://github.com/open-feature/java-sdk/commit/58df782b767617c63628ddb9ece3ed3816d865ad)) +* **deps:** update google-github-actions/release-please-action digest to 8475937 ([#406](https://github.com/open-feature/java-sdk/issues/406)) ([cd27e38](https://github.com/open-feature/java-sdk/commit/cd27e38f676417e37f7a75cc8413b42350c088cc)) +* **deps:** update google-github-actions/release-please-action digest to c078ea3 ([#387](https://github.com/open-feature/java-sdk/issues/387)) ([702957c](https://github.com/open-feature/java-sdk/commit/702957c517345906db80c0805e02e22ee18fa70c)) +* **deps:** update google-github-actions/release-please-action digest to ee9822e ([#366](https://github.com/open-feature/java-sdk/issues/366)) ([6d7c43d](https://github.com/open-feature/java-sdk/commit/6d7c43d120d025d180a446ba7769109b94e1be3c)) +* **deps:** update google-github-actions/release-please-action digest to f7edb9e ([#384](https://github.com/open-feature/java-sdk/issues/384)) ([22828d1](https://github.com/open-feature/java-sdk/commit/22828d1d3f59371205d36b8419dd61647046043f)) +* expose get value for metadata ([#468](https://github.com/open-feature/java-sdk/issues/468)) ([93dde1d](https://github.com/open-feature/java-sdk/commit/93dde1d259e86b00db701a753b84ad2c253e21ec)) +* rename flag metadata ([#478](https://github.com/open-feature/java-sdk/issues/478)) ([ecfeddf](https://github.com/open-feature/java-sdk/commit/ecfeddf0f67c4d9cf34530f957d139344b622b51)) +* rename integration tests e2e ([#417](https://github.com/open-feature/java-sdk/issues/417)) ([a5c93ac](https://github.com/open-feature/java-sdk/commit/a5c93aca0a718a5760bc346f27fd70b59432d11a)) +* seperate release plugins to a profile ([#467](https://github.com/open-feature/java-sdk/issues/467)) ([31f2148](https://github.com/open-feature/java-sdk/commit/31f214826453a10d7bef2d1d59033febf75dbb76)) +* update copy and links on the readme ([#488](https://github.com/open-feature/java-sdk/issues/488)) ([6cd2081](https://github.com/open-feature/java-sdk/commit/6cd208198ce786ce173eea2dbcffb6338ba28c86)) +* update readme for events ([#507](https://github.com/open-feature/java-sdk/issues/507)) ([c115e96](https://github.com/open-feature/java-sdk/commit/c115e96ae67ce7d006d8ee495685d07895c06774)) +* update readme using template ([#382](https://github.com/open-feature/java-sdk/issues/382)) ([f51d020](https://github.com/open-feature/java-sdk/commit/f51d0201c62b558a89a1e3ab77e666ce98ecba0b)) + ## [1.3.1](https://github.com/open-feature/java-sdk/compare/v1.3.0...v1.3.1) (2023-03-28) diff --git a/README.md b/README.md index 2d2d79bd..8ef4a053 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Note that this library is intended to be used in server-side contexts and has no dev.openfeature sdk - 1.3.1 + 1.4.0 ``` @@ -67,7 +67,7 @@ If you would like snapshot builds, this is the relevant repository information: ```groovy dependencies { - implementation 'dev.openfeature:sdk:1.3.1' + implementation 'dev.openfeature:sdk:1.4.0' } ``` diff --git a/pom.xml b/pom.xml index af8807b8..3ec58097 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ dev.openfeature sdk - 1.3.1 + 1.4.0 UTF-8 diff --git a/version.txt b/version.txt index 3a3cd8cc..88c5fb89 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.3.1 +1.4.0