From 2f29d66e4739eee157eb897db5a4f7ca19c9d305 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 00:36:15 -0500 Subject: [PATCH 01/90] chore(deps): update dependency php to v8 (#16) * chore(deps): update dependency php to v8 * build: update .tool-versions to point to 8.2.0 Signed-off-by: Tom Carrio Signed-off-by: Tom Carrio Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .tool-versions | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.tool-versions b/.tool-versions index 8d0b8372..24339636 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,4 @@ -php 7.4.33 +# php 7.4.33 # php 8.0.24 -# php 8.1.11 \ No newline at end of file +# php 8.1.11 +php 8.2.0 From 9a56d765252c334158d8a7894600a398e4799c49 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 00:36:27 -0500 Subject: [PATCH 02/90] chore(deps): update dependency psalm/plugin-mockery to ^0.11.0 (#12) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- src/CloudBees/composer.json | 2 +- src/Flagd/composer.json | 2 +- src/Split/composer.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CloudBees/composer.json b/src/CloudBees/composer.json index e855b74f..a3f3c6d8 100644 --- a/src/CloudBees/composer.json +++ b/src/CloudBees/composer.json @@ -40,7 +40,7 @@ "phpstan/phpstan": "~1.9.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", - "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-mockery": "^0.11.0", "psalm/plugin-phpunit": "^0.18.0", "ramsey/coding-standard": "^2.0.3", "ramsey/composer-repl": "^1.4", diff --git a/src/Flagd/composer.json b/src/Flagd/composer.json index 68ab618f..b9f0ccc6 100644 --- a/src/Flagd/composer.json +++ b/src/Flagd/composer.json @@ -42,7 +42,7 @@ "phpstan/phpstan": "~1.9.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", - "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-mockery": "^0.11.0", "psalm/plugin-phpunit": "^0.18.0", "ramsey/coding-standard": "^2.0.3", "ramsey/composer-repl": "^1.4", diff --git a/src/Split/composer.json b/src/Split/composer.json index de496a9a..3eee1b7f 100644 --- a/src/Split/composer.json +++ b/src/Split/composer.json @@ -40,7 +40,7 @@ "phpstan/phpstan": "~1.9.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", - "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-mockery": "^0.11.0", "psalm/plugin-phpunit": "^0.18.0", "ramsey/coding-standard": "^2.0.3", "ramsey/composer-repl": "^1.4", From be3f1e9ed37dee4bbce8e3701e4693c1b949c398 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 26 Dec 2022 20:20:18 -0500 Subject: [PATCH 03/90] feat: otel hook (#22) * feat: added OTel hook for OpenFeature - new statically registerable OTel hook for OpenFeature - move hooks and providers into independent directories - enable PHP 8.2 runner - disable integration tests since none exist - utilize test wrapper script definition in CI Ref: #6 Signed-off-by: Tom Carrio Signed-off-by: Tom Carrio * chore: revert composer script usage and add integration tests Signed-off-by: Tom Carrio * ci: revert composer script usage for unit/integration tests Signed-off-by: Tom Carrio * ci: fix reference to integration setup Signed-off-by: Tom Carrio Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 28 ++-- .gitmodules | 5 +- .gitsplit.yml | 8 +- README.md | 9 +- hooks/.gitkeep | 0 .../.github/workflows/release-please.yml | 0 .../OpenTelemetry}/.gitignore | 0 .../.release-please-manifest.json | 0 hooks/OpenTelemetry/README.md | 56 ++++++++ hooks/OpenTelemetry/composer.json | 136 ++++++++++++++++++ .../OpenTelemetry}/examples/.gitignore | 0 .../OTelManualInstrumentation/README.md | 3 + .../OTelManualInstrumentation/composer.json | 21 +++ .../OTelManualInstrumentation/src/main.php | 3 + .../OpenTelemetry}/phpcs.xml.dist | 0 .../OpenTelemetry}/phpstan.neon.dist | 0 .../OpenTelemetry}/phpunit.xml.dist | 0 .../OpenTelemetry}/psalm-baseline.xml | 0 .../OpenTelemetry}/psalm.xml | 0 .../OpenTelemetry}/release-please-config.json | 0 hooks/OpenTelemetry/src/OpenTelemetryHook.php | 91 ++++++++++++ hooks/OpenTelemetry/src/TracerHelper.php | 40 ++++++ hooks/OpenTelemetry/tests/TestCase.php | 40 ++++++ .../integration/OpenTelemetryHookTest.php | 26 ++++ .../tests/unit/OpenTelemetryHookTest.php | 26 ++++ providers/.gitkeep | 0 .../.github/workflows/release-please.yml | 0 {src/Flagd => providers/CloudBees}/.gitignore | 0 .../CloudBees}/.release-please-manifest.json | 0 {src => providers}/CloudBees/README.md | 0 {src => providers}/CloudBees/composer.json | 0 .../CloudBees}/examples/.gitignore | 0 .../CloudBees/examples/CloudBees/README.md | 0 .../examples/CloudBees/composer.json | 0 .../CloudBees/examples/CloudBees/src/main.php | 0 .../CloudBees}/phpcs.xml.dist | 0 .../CloudBees}/phpstan.neon.dist | 0 .../CloudBees}/phpunit.xml.dist | 0 .../CloudBees}/psalm-baseline.xml | 0 {src/Split => providers/CloudBees}/psalm.xml | 0 .../CloudBees/release-please-config.json | 0 .../scripts/scaffold-integration-tests.py | 0 .../CloudBees/scripts/seed-data.json | 0 .../CloudBees/src/CloudBeesProvider.php | 0 .../CloudBees/src/context/ContextAdapter.php | 0 .../src/errors/InvalidJsonTypeException.php | 0 .../src/errors/JsonParseException.php | 0 .../src/transformers/IdentityTransformer.php | 0 .../src/transformers/JsonTransformer.php | 0 .../CloudBees/tests/TestCase.php | 0 .../integration/CloudBeesProviderTest.php | 0 .../tests/unit/JsonTransformerTest.php | 0 .../.github/workflows/release-please.yml | 0 {src/Split => providers/Flagd}/.gitignore | 0 .../Flagd}/.release-please-manifest.json | 0 {src => providers}/Flagd/README.md | 0 {src => providers}/Flagd/composer.json | 0 .../Flagd}/examples/.gitignore | 0 .../Flagd/examples/Grpc/README.md | 0 .../Flagd/examples/Grpc/composer.json | 0 .../Flagd/examples/Grpc/src/main.php | 0 .../Flagd/examples/Http/README.md | 0 .../Flagd/examples/Http/composer.json | 0 .../Flagd/examples/Http/src/main.php | 0 {src/Split => providers/Flagd}/phpcs.xml.dist | 0 {src => providers}/Flagd/phpstan.neon.dist | 0 {src => providers}/Flagd/phpunit.xml.dist | 0 {src => providers}/Flagd/proto/README.md | 0 .../php/GPBMetadata/Schema/V1/Schema.php | Bin .../php/Schema/V1/EventStreamResponse.php | 0 .../php/Schema/V1/ResolveBooleanRequest.php | 0 .../php/Schema/V1/ResolveBooleanResponse.php | 0 .../php/Schema/V1/ResolveFloatRequest.php | 0 .../php/Schema/V1/ResolveFloatResponse.php | 0 .../proto/php/Schema/V1/ResolveIntRequest.php | 0 .../php/Schema/V1/ResolveIntResponse.php | 0 .../php/Schema/V1/ResolveObjectRequest.php | 0 .../php/Schema/V1/ResolveObjectResponse.php | 0 .../php/Schema/V1/ResolveStringRequest.php | 0 .../php/Schema/V1/ResolveStringResponse.php | 0 .../proto/php/Schema/V1/ServiceClient.php | 0 .../Flagd}/psalm-baseline.xml | 0 {src => providers}/Flagd/psalm.xml | 0 .../Flagd/release-please-config.json | 0 {src => providers}/Flagd/schemas | 0 .../Flagd/src/FlagdProvider.php | 0 .../common/EvaluationContextArrayFactory.php | 0 .../src/common/ResponseCodeErrorCodeMap.php | 0 .../Flagd/src/common/SafeArrayAccessor.php | 0 .../Flagd/src/config/Config.php | 0 .../Flagd/src/config/ConfigFactory.php | 0 .../Flagd/src/config/Defaults.php | 0 .../Flagd/src/config/HttpConfig.php | 0 .../Flagd/src/config/IConfig.php | 0 .../Flagd/src/config/IHttpConfig.php | 0 .../Flagd/src/config/Protocols.php | 0 .../Flagd/src/config/Validator.php | 0 .../src/errors/InvalidConfigException.php | 0 .../Flagd/src/errors/InvalidTypeException.php | 0 .../src/errors/RequestBuildException.php | 0 .../Flagd/src/grpc/GrpcService.php | 0 .../grpc/ResponseResolutionDetailsAdapter.php | 0 .../Flagd/src/grpc/ResponseValidator.php | 0 .../FlagdResponseResolutionDetailsAdapter.php | 0 .../Flagd/src/http/FlagdResponseValidator.php | 0 .../Flagd/src/http/GrpcWebEndpoint.php | 0 .../Flagd/src/http/HttpService.php | 0 {src => providers}/Flagd/src/http/Method.php | 0 .../Flagd/src/service/ServiceFactory.php | 0 .../Flagd/src/service/ServiceInterface.php | 0 {src => providers}/Flagd/tests/TestCase.php | 0 .../Flagd/tests/unit/FlagdProviderTest.php | 0 .../.github/workflows/release-please.yml | 18 +++ providers/Split/.gitignore | 3 + providers/Split/.release-please-manifest.json | 3 + {src => providers}/Split/README.md | 0 {src => providers}/Split/composer.json | 0 providers/Split/examples/.gitignore | 2 + .../Split/examples/SplitSDK/README.md | 0 .../Split/examples/SplitSDK/composer.json | 0 .../Split/examples/SplitSDK/src/main.php | 0 providers/Split/phpcs.xml.dist | 28 ++++ providers/Split/phpstan.neon.dist | 9 ++ providers/Split/phpunit.xml.dist | 28 ++++ providers/Split/psalm-baseline.xml | 2 + providers/Split/psalm.xml | 17 +++ providers/Split/release-please-config.json | 12 ++ .../Split/src/SplitProvider.php | 0 .../errors/InvalidTreatmentTypeException.php | 0 .../errors/SplitFactoryCreationException.php | 0 .../errors/TargetingKeyMissingException.php | 0 .../Split/src/treatments/TreatmentParser.php | 0 .../src/treatments/TreatmentValidator.php | 0 {src => providers}/Split/tests/TestCase.php | 0 .../tests/integration/SplitProviderTest.php | 0 .../Split/tests/integration/files/splits.yml | 0 .../Split/tests/unit/SplitProviderTest.php | 0 137 files changed, 595 insertions(+), 19 deletions(-) create mode 100644 hooks/.gitkeep rename {src/CloudBees => hooks/OpenTelemetry}/.github/workflows/release-please.yml (100%) rename {src/CloudBees => hooks/OpenTelemetry}/.gitignore (100%) rename {src/CloudBees => hooks/OpenTelemetry}/.release-please-manifest.json (100%) create mode 100644 hooks/OpenTelemetry/README.md create mode 100644 hooks/OpenTelemetry/composer.json rename {src/CloudBees => hooks/OpenTelemetry}/examples/.gitignore (100%) create mode 100644 hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md create mode 100644 hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json create mode 100644 hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php rename {src/CloudBees => hooks/OpenTelemetry}/phpcs.xml.dist (100%) rename {src/CloudBees => hooks/OpenTelemetry}/phpstan.neon.dist (100%) rename {src/CloudBees => hooks/OpenTelemetry}/phpunit.xml.dist (100%) rename {src/CloudBees => hooks/OpenTelemetry}/psalm-baseline.xml (100%) rename {src/CloudBees => hooks/OpenTelemetry}/psalm.xml (100%) rename {src/Split => hooks/OpenTelemetry}/release-please-config.json (100%) create mode 100644 hooks/OpenTelemetry/src/OpenTelemetryHook.php create mode 100644 hooks/OpenTelemetry/src/TracerHelper.php create mode 100644 hooks/OpenTelemetry/tests/TestCase.php create mode 100644 hooks/OpenTelemetry/tests/integration/OpenTelemetryHookTest.php create mode 100644 hooks/OpenTelemetry/tests/unit/OpenTelemetryHookTest.php create mode 100644 providers/.gitkeep rename {src/Flagd => providers/CloudBees}/.github/workflows/release-please.yml (100%) rename {src/Flagd => providers/CloudBees}/.gitignore (100%) rename {src/Flagd => providers/CloudBees}/.release-please-manifest.json (100%) rename {src => providers}/CloudBees/README.md (100%) rename {src => providers}/CloudBees/composer.json (100%) rename {src/Flagd => providers/CloudBees}/examples/.gitignore (100%) rename {src => providers}/CloudBees/examples/CloudBees/README.md (100%) rename {src => providers}/CloudBees/examples/CloudBees/composer.json (100%) rename {src => providers}/CloudBees/examples/CloudBees/src/main.php (100%) rename {src/Flagd => providers/CloudBees}/phpcs.xml.dist (100%) rename {src/Split => providers/CloudBees}/phpstan.neon.dist (100%) rename {src/Split => providers/CloudBees}/phpunit.xml.dist (100%) rename {src/Flagd => providers/CloudBees}/psalm-baseline.xml (100%) rename {src/Split => providers/CloudBees}/psalm.xml (100%) rename {src => providers}/CloudBees/release-please-config.json (100%) rename {src => providers}/CloudBees/scripts/scaffold-integration-tests.py (100%) rename {src => providers}/CloudBees/scripts/seed-data.json (100%) rename {src => providers}/CloudBees/src/CloudBeesProvider.php (100%) rename {src => providers}/CloudBees/src/context/ContextAdapter.php (100%) rename {src => providers}/CloudBees/src/errors/InvalidJsonTypeException.php (100%) rename {src => providers}/CloudBees/src/errors/JsonParseException.php (100%) rename {src => providers}/CloudBees/src/transformers/IdentityTransformer.php (100%) rename {src => providers}/CloudBees/src/transformers/JsonTransformer.php (100%) rename {src => providers}/CloudBees/tests/TestCase.php (100%) rename {src => providers}/CloudBees/tests/integration/CloudBeesProviderTest.php (100%) rename {src => providers}/CloudBees/tests/unit/JsonTransformerTest.php (100%) rename {src/Split => providers/Flagd}/.github/workflows/release-please.yml (100%) rename {src/Split => providers/Flagd}/.gitignore (100%) rename {src/Split => providers/Flagd}/.release-please-manifest.json (100%) rename {src => providers}/Flagd/README.md (100%) rename {src => providers}/Flagd/composer.json (100%) rename {src/Split => providers/Flagd}/examples/.gitignore (100%) rename {src => providers}/Flagd/examples/Grpc/README.md (100%) rename {src => providers}/Flagd/examples/Grpc/composer.json (100%) rename {src => providers}/Flagd/examples/Grpc/src/main.php (100%) rename {src => providers}/Flagd/examples/Http/README.md (100%) rename {src => providers}/Flagd/examples/Http/composer.json (100%) rename {src => providers}/Flagd/examples/Http/src/main.php (100%) rename {src/Split => providers/Flagd}/phpcs.xml.dist (100%) rename {src => providers}/Flagd/phpstan.neon.dist (100%) rename {src => providers}/Flagd/phpunit.xml.dist (100%) rename {src => providers}/Flagd/proto/README.md (100%) rename {src => providers}/Flagd/proto/php/GPBMetadata/Schema/V1/Schema.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/EventStreamResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveIntRequest.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveIntResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveStringRequest.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ResolveStringResponse.php (100%) rename {src => providers}/Flagd/proto/php/Schema/V1/ServiceClient.php (100%) rename {src/Split => providers/Flagd}/psalm-baseline.xml (100%) rename {src => providers}/Flagd/psalm.xml (100%) rename {src => providers}/Flagd/release-please-config.json (100%) rename {src => providers}/Flagd/schemas (100%) rename {src => providers}/Flagd/src/FlagdProvider.php (100%) rename {src => providers}/Flagd/src/common/EvaluationContextArrayFactory.php (100%) rename {src => providers}/Flagd/src/common/ResponseCodeErrorCodeMap.php (100%) rename {src => providers}/Flagd/src/common/SafeArrayAccessor.php (100%) rename {src => providers}/Flagd/src/config/Config.php (100%) rename {src => providers}/Flagd/src/config/ConfigFactory.php (100%) rename {src => providers}/Flagd/src/config/Defaults.php (100%) rename {src => providers}/Flagd/src/config/HttpConfig.php (100%) rename {src => providers}/Flagd/src/config/IConfig.php (100%) rename {src => providers}/Flagd/src/config/IHttpConfig.php (100%) rename {src => providers}/Flagd/src/config/Protocols.php (100%) rename {src => providers}/Flagd/src/config/Validator.php (100%) rename {src => providers}/Flagd/src/errors/InvalidConfigException.php (100%) rename {src => providers}/Flagd/src/errors/InvalidTypeException.php (100%) rename {src => providers}/Flagd/src/errors/RequestBuildException.php (100%) rename {src => providers}/Flagd/src/grpc/GrpcService.php (100%) rename {src => providers}/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php (100%) rename {src => providers}/Flagd/src/grpc/ResponseValidator.php (100%) rename {src => providers}/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php (100%) rename {src => providers}/Flagd/src/http/FlagdResponseValidator.php (100%) rename {src => providers}/Flagd/src/http/GrpcWebEndpoint.php (100%) rename {src => providers}/Flagd/src/http/HttpService.php (100%) rename {src => providers}/Flagd/src/http/Method.php (100%) rename {src => providers}/Flagd/src/service/ServiceFactory.php (100%) rename {src => providers}/Flagd/src/service/ServiceInterface.php (100%) rename {src => providers}/Flagd/tests/TestCase.php (100%) rename {src => providers}/Flagd/tests/unit/FlagdProviderTest.php (100%) create mode 100644 providers/Split/.github/workflows/release-please.yml create mode 100644 providers/Split/.gitignore create mode 100644 providers/Split/.release-please-manifest.json rename {src => providers}/Split/README.md (100%) rename {src => providers}/Split/composer.json (100%) create mode 100644 providers/Split/examples/.gitignore rename {src => providers}/Split/examples/SplitSDK/README.md (100%) rename {src => providers}/Split/examples/SplitSDK/composer.json (100%) rename {src => providers}/Split/examples/SplitSDK/src/main.php (100%) create mode 100644 providers/Split/phpcs.xml.dist create mode 100644 providers/Split/phpstan.neon.dist create mode 100644 providers/Split/phpunit.xml.dist create mode 100644 providers/Split/psalm-baseline.xml create mode 100644 providers/Split/psalm.xml create mode 100644 providers/Split/release-please-config.json rename {src => providers}/Split/src/SplitProvider.php (100%) rename {src => providers}/Split/src/errors/InvalidTreatmentTypeException.php (100%) rename {src => providers}/Split/src/errors/SplitFactoryCreationException.php (100%) rename {src => providers}/Split/src/errors/TargetingKeyMissingException.php (100%) rename {src => providers}/Split/src/treatments/TreatmentParser.php (100%) rename {src => providers}/Split/src/treatments/TreatmentValidator.php (100%) rename {src => providers}/Split/tests/TestCase.php (100%) rename {src => providers}/Split/tests/integration/SplitProviderTest.php (100%) rename {src => providers}/Split/tests/integration/files/splits.yml (100%) rename {src => providers}/Split/tests/unit/SplitProviderTest.php (100%) diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 5741bae3..26f4d021 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -12,8 +12,12 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-version: ['7.4', '8.0', '8.1'] - project: ['Flagd', 'Split', 'CloudBees'] + php-version: ['7.4', '8.0', '8.1', '8.2'] + project-dir: + - hooks/OpenTelemetry + - providers/Flagd + - providers/Split + - providers/CloudBees # todo exclude some matrix combinations based on php version requirements # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#excluding-matrix-configurations @@ -40,47 +44,47 @@ jobs: id: composer-cache uses: actions/cache@v3 with: - path: src/${{ matrix.project }}/vendor + path: ${{ matrix.project-dir }}/vendor key: ${{ runner.os }}-${{ matrix.php-version }}-php-${{ hashFiles('**/composer.json') }} restore-keys: | ${{ runner.os }}-${{ matrix.php-version }}-php- - name: Install dependencies if: steps.composer-cache.outputs.cache-hit != 'true' - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: composer install --prefer-dist --no-progress --no-suggest - name: Validate Packages composer.json - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: composer validate - name: Check Style - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: vendor/bin/phpcs - name: Run Phan - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} env: PHAN_DISABLE_XDEBUG_WARN: 1 run: vendor/bin/phan - name: Run Psalm - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: vendor/bin/psalm --output-format=github --php-version=${{ matrix.php-version }} - name: Run Phpstan - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: vendor/bin/phpstan analyse --error-format=github - name: Run PHPUnit (unit tests) - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: | composer run dev:test:unit:setup vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover --testsuite unit composer run dev:test:unit:teardown - name: Run PHPUnit (integration tests) - working-directory: src/${{ matrix.project }} + working-directory: ${{ matrix.project-dir }} run: | composer run dev:test:integration:setup vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover --testsuite integration @@ -88,7 +92,7 @@ jobs: ### TODO: Enable codecov support # - name: Code Coverage - # working-directory: src/${{ matrix.project }} + # working-directory: ${{ matrix.project-dir }} # run: bash <(curl -s https://codecov.io/bash) -F ${{ matrix.php-version }} ### TODO: Replicate any necessary package checks diff --git a/.gitmodules b/.gitmodules index 0e03a2f9..4c5f1304 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "schemas"] - path = src/Flagd/schemas + path = providers/Flagd/schemas + url = https://github.com/tcarrio/schemas/ +[submodule "providers/Flagd/schemas"] + path = providers/Flagd/schemas url = https://github.com/tcarrio/schemas/ diff --git a/.gitsplit.yml b/.gitsplit.yml index 607974d4..9318e9e3 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -6,11 +6,13 @@ project_url: "https://github.com/open-feature/php-sdk-contrib.git" # List of splits. splits: - - prefix: "src/Flagd" + - prefix: "hooks/OpenTelemetry" + target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/otel-hook.git" + - prefix: "providers/Flagd" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/flagd-provider.git" - - prefix: "src/Split" + - prefix: "providers/Split" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/split-provider.git" - - prefix: "src/CloudBees" + - prefix: "providers/CloudBees" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/cloudbees-provider.git" # List of references to split (defined as regexp) diff --git a/README.md b/README.md index 6e744c7e..68bd13aa 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,12 @@ The `php-contrib-sdk` repository is a monorepository containing various providers and hooks for OpenFeature's PHP SDK. Packages include: -- [Flagd](./src/Flagd/README.md) -- [Split](./src/Split/README.md) -- [CloudBees](./src/CloudBees/README.md) +- Providers + - [Flagd](./providers/Flagd/README.md) + - [Split](./providers/Split/README.md) + - [CloudBees](./providers/CloudBees/README.md) +- Hooks + - [OpenTelemetry](./hooks/OpenTelemetry/README.md) ### Status diff --git a/hooks/.gitkeep b/hooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/CloudBees/.github/workflows/release-please.yml b/hooks/OpenTelemetry/.github/workflows/release-please.yml similarity index 100% rename from src/CloudBees/.github/workflows/release-please.yml rename to hooks/OpenTelemetry/.github/workflows/release-please.yml diff --git a/src/CloudBees/.gitignore b/hooks/OpenTelemetry/.gitignore similarity index 100% rename from src/CloudBees/.gitignore rename to hooks/OpenTelemetry/.gitignore diff --git a/src/CloudBees/.release-please-manifest.json b/hooks/OpenTelemetry/.release-please-manifest.json similarity index 100% rename from src/CloudBees/.release-please-manifest.json rename to hooks/OpenTelemetry/.release-please-manifest.json diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md new file mode 100644 index 00000000..67f80885 --- /dev/null +++ b/hooks/OpenTelemetry/README.md @@ -0,0 +1,56 @@ +# OpenFeature OpenTelemetry Hook + +[![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) +[![Latest Stable Version](http://poser.pugx.org/open-feature/otel-hook/v)](https://packagist.org/packages/open-feature/otel-hook) +[![Total Downloads](http://poser.pugx.org/open-feature/otel-hook/downloads)](https://packagist.org/packages/open-feature/otel-hook) +![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +[![License](http://poser.pugx.org/open-feature/otel-hook/license)](https://packagist.org/packages/open-feature/otel-hook) + +## Overview + +OpenTelemetry is an open specification for distributed tracing, metrics, and logging. It defines a semantic convention for feature flagging which is utilized in this hook to report flag evaluations. + +This package also builds on various PSRs (PHP Standards Recommendations) such as the Logger interfaces (PSR-3) and the Basic and Extended Coding Standards (PSR-1 and PSR-12). + +### OpenTelemetry Package Status + +The OpenTelemetry package for PHP is still in beta, so there could be changes required. However, it exposes global primitives for span retrieval that should not require any configuration upfront for the provider to just work. + +## Installation + +``` +$ composer require open-feature/otel-hook // installs the latest version +``` + +## Usage + +The `OpenTelemetryHook` should be registered to the OpenFeatureAPI globally for use across all evaluations. + +It makes use of the `open-telemetry/api` packages `Globals` utility for current span retrieval, thus has +no dependency on configuration or injection of tracers. + +```php +use OpenFeature\Hooks\OpenTelemetry\OpenTelemetryHook; + +OpenTelemetryHook::register(); +``` + +For more information on OpenTelemetry, check out [their documentation](https://opentelemetry.io/docs/instrumentation/php/). + +## Development + +### PHP Versioning + +This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. + +This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. + +### Installation and Dependencies + +Install dependencies with `composer install`. `composer install` will update the `composer.lock` with the most recent compatible versions. + +We value having as few runtime dependencies as possible. The addition of any dependencies requires careful consideration and review. + +### Testing + +Run tests with `composer run test`. \ No newline at end of file diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json new file mode 100644 index 00000000..a3819459 --- /dev/null +++ b/hooks/OpenTelemetry/composer.json @@ -0,0 +1,136 @@ +{ + "name": "open-feature/split-provider", + "description": "The Split provider package for OpenFeature", + "license": "Apache-2.0", + "type": "library", + "keywords": [ + "featureflags", + "featureflagging", + "openfeature", + "split", + "splitio", + "provider" + ], + "authors": [ + { + "name": "OpenFeature PHP Maintainers", + "homepage": "https://github.com/orgs/open-feature/teams/php-maintainer" + }, + { + "name": "open-feature/php-sdk-contrib Contributors", + "homepage": "https://github.com/open-feature/php-sdk-contrib/graphs/contributors" + } + ], + "require": { + "php": "^7.4 || ^8", + "open-feature/sdk": "^1.1.0", + "open-telemetry/api": "^0.0.17", + "splitsoftware/split-sdk-php": "^7.1" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.25", + "friendsofphp/php-cs-fixer": "^3.13", + "hamcrest/hamcrest-php": "^2.0", + "mdwheele/zalgo": "^0.3.1", + "mikey179/vfsstream": "v1.6.11", + "mockery/mockery": "^1.5", + "phan/phan": "^5.4", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan-mockery": "^1.0", + "phpstan/phpstan-phpunit": "^1.1", + "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-phpunit": "^0.18.0", + "ramsey/coding-standard": "^2.0.3", + "ramsey/composer-repl": "^1.4", + "ramsey/conventional-commits": "^1.3", + "roave/security-advisories": "dev-latest", + "spatie/phpunit-snapshot-assertions": "^4.2", + "vimeo/psalm": "~4.30.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "OpenFeature\\Hooks\\OpenTelemetry\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "OpenFeature\\Hooks\\OpenTelemetry\\Test\\": "tests" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "captainhook/plugin-composer": true, + "ramsey/composer-repl": true + }, + "sort-packages": true + }, + "extra": { + "captainhook": { + "force-install": false + } + }, + "scripts": { + "dev:analyze": [ + "@dev:analyze:phpstan", + "@dev:analyze:psalm" + ], + "dev:analyze:phpstan": "phpstan analyse --ansi --debug --memory-limit=512M", + "dev:analyze:psalm": "psalm", + "dev:build:clean": "git clean -fX build/", + "dev:lint": [ + "@dev:lint:syntax", + "@dev:lint:style" + ], + "dev:lint:fix": "phpcbf", + "dev:lint:style": "phpcs --colors", + "dev:lint:syntax": "parallel-lint --colors src/ tests/", + "dev:test": [ + "@dev:lint", + "@dev:analyze", + "@dev:test:unit", + "@dev:test:integration" + ], + "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml", + "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/", + "dev:test:unit": [ + "@dev:test:unit:setup", + "phpunit --colors=always --testdox --testsuite=unit", + "@dev:test:unit:teardown" + ], + "dev:test:unit:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:unit:setup": "echo 'Setup for unit tests...'", + "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", + "dev:test:integration": [ + "@dev:test:integration:setup", + "echo 'No integration tests to run'", + "@dev:test:integration:teardown" + ], + "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:integration:setup": "echo 'Setup for integration tests...'", + "dev:test:integration:teardown": "echo 'Tore down integration tests...'", + "test": "@dev:test" + }, + "scripts-descriptions": { + "dev:analyze": "Runs all static analysis checks.", + "dev:analyze:phpstan": "Runs the PHPStan static analyzer.", + "dev:analyze:psalm": "Runs the Psalm static analyzer.", + "dev:build:clean": "Cleans the build/ directory.", + "dev:lint": "Runs all linting checks.", + "dev:lint:fix": "Auto-fixes coding standards issues, if possible.", + "dev:lint:style": "Checks for coding standards issues.", + "dev:lint:syntax": "Checks for syntax errors.", + "dev:test": "Runs linting, static analysis, and unit tests.", + "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.", + "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.", + "dev:test:unit": "Runs unit tests.", + "test": "Runs linting, static analysis, and unit tests." + } +} diff --git a/src/CloudBees/examples/.gitignore b/hooks/OpenTelemetry/examples/.gitignore similarity index 100% rename from src/CloudBees/examples/.gitignore rename to hooks/OpenTelemetry/examples/.gitignore diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md new file mode 100644 index 00000000..9e88acd4 --- /dev/null +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md @@ -0,0 +1,3 @@ +# OpenFeature OpenTelemetry Hook example + +This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature. diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json new file mode 100644 index 00000000..7894e958 --- /dev/null +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json @@ -0,0 +1,21 @@ +{ + "name": "open-feature/otel-manual-instrumentation-example", + "description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation", + "type": "project", + "license": "Apache-2.0", + "autoload": { + "psr-4": { + "OpenFeature\\Providers\\Examples\\SplitSdkExample\\": "src/" + } + }, + "authors": [ + { + "name": "Tom Carrio", + "email": "tom@carrio.dev" + } + ], + "require": { + "open-feature/sdk": "^1.1.2", + "open-telemetry/api": "^0.0.17" + } +} diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php new file mode 100644 index 00000000..207eebfb --- /dev/null +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php @@ -0,0 +1,3 @@ +addHooks(self::$instance); + self::$registeredHook = true; + } + + private static ?OpenTelemetryHook $instance = null; + private static bool $registeredHook = false; + + public function before(HookContext $context, HookHints $hints): ?EvaluationContext + { + return null; + } + + public function after(HookContext $context, ResolutionDetails $details, HookHints $hints): void + { + $span = Span::getCurrent(); + + $span->addEvent(self::EVENT_NAME, [ + self::FLAG_KEY => $context->getFlagKey(), + self::FLAG_PROVIDER_NAME => OpenFeatureAPI::getInstance()->getProvider()->getMetadata()->getName(), + self::FLAG_VARIANT => $details->getVariant(), + ]); + } + + public function error(HookContext $context, Throwable $error, HookHints $hints): void + { + $span = Span::getCurrent(); + + $span->recordException($error, [ + self::FLAG_KEY => $context->getFlagKey(), + self::FLAG_PROVIDER_NAME => OpenFeatureAPI::getInstance()->getProvider()->getMetadata()->getName(), + ]); + } + + public function finally(HookContext $context, HookHints $hints): void + { + // no-op + } + + public function supportsFlagValueType(string $flagValueType): bool + { + return true; + } +} diff --git a/hooks/OpenTelemetry/src/TracerHelper.php b/hooks/OpenTelemetry/src/TracerHelper.php new file mode 100644 index 00000000..5d08c4b5 --- /dev/null +++ b/hooks/OpenTelemetry/src/TracerHelper.php @@ -0,0 +1,40 @@ +has(TracerInterface::class)) { + /** @var TracerInterface|null $maybeTracer */ + $maybeTracer = $container->get(TracerInterface::class); + + if ($maybeTracer instanceof TracerInterface) { + return $maybeTracer; + } + } + } + + return Globals::tracerProvider()->getTracer('open-feature/otel-hook', '0.0.1'); + } +} diff --git a/hooks/OpenTelemetry/tests/TestCase.php b/hooks/OpenTelemetry/tests/TestCase.php new file mode 100644 index 00000000..21e59867 --- /dev/null +++ b/hooks/OpenTelemetry/tests/TestCase.php @@ -0,0 +1,40 @@ + $class + * @param mixed ...$arguments + * + * @return T & MockInterface + * + * @template T + * + * phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function mockery(string $class, ...$arguments) + { + /** @var T & MockInterface $mock */ + $mock = Mockery::mock($class, ...$arguments); + + return $mock; + } +} diff --git a/hooks/OpenTelemetry/tests/integration/OpenTelemetryHookTest.php b/hooks/OpenTelemetry/tests/integration/OpenTelemetryHookTest.php new file mode 100644 index 00000000..22bd101c --- /dev/null +++ b/hooks/OpenTelemetry/tests/integration/OpenTelemetryHookTest.php @@ -0,0 +1,26 @@ +assertNotEmpty($api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } +} diff --git a/hooks/OpenTelemetry/tests/unit/OpenTelemetryHookTest.php b/hooks/OpenTelemetry/tests/unit/OpenTelemetryHookTest.php new file mode 100644 index 00000000..c793d9d4 --- /dev/null +++ b/hooks/OpenTelemetry/tests/unit/OpenTelemetryHookTest.php @@ -0,0 +1,26 @@ +assertNotEmpty($api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } +} diff --git a/providers/.gitkeep b/providers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/Flagd/.github/workflows/release-please.yml b/providers/CloudBees/.github/workflows/release-please.yml similarity index 100% rename from src/Flagd/.github/workflows/release-please.yml rename to providers/CloudBees/.github/workflows/release-please.yml diff --git a/src/Flagd/.gitignore b/providers/CloudBees/.gitignore similarity index 100% rename from src/Flagd/.gitignore rename to providers/CloudBees/.gitignore diff --git a/src/Flagd/.release-please-manifest.json b/providers/CloudBees/.release-please-manifest.json similarity index 100% rename from src/Flagd/.release-please-manifest.json rename to providers/CloudBees/.release-please-manifest.json diff --git a/src/CloudBees/README.md b/providers/CloudBees/README.md similarity index 100% rename from src/CloudBees/README.md rename to providers/CloudBees/README.md diff --git a/src/CloudBees/composer.json b/providers/CloudBees/composer.json similarity index 100% rename from src/CloudBees/composer.json rename to providers/CloudBees/composer.json diff --git a/src/Flagd/examples/.gitignore b/providers/CloudBees/examples/.gitignore similarity index 100% rename from src/Flagd/examples/.gitignore rename to providers/CloudBees/examples/.gitignore diff --git a/src/CloudBees/examples/CloudBees/README.md b/providers/CloudBees/examples/CloudBees/README.md similarity index 100% rename from src/CloudBees/examples/CloudBees/README.md rename to providers/CloudBees/examples/CloudBees/README.md diff --git a/src/CloudBees/examples/CloudBees/composer.json b/providers/CloudBees/examples/CloudBees/composer.json similarity index 100% rename from src/CloudBees/examples/CloudBees/composer.json rename to providers/CloudBees/examples/CloudBees/composer.json diff --git a/src/CloudBees/examples/CloudBees/src/main.php b/providers/CloudBees/examples/CloudBees/src/main.php similarity index 100% rename from src/CloudBees/examples/CloudBees/src/main.php rename to providers/CloudBees/examples/CloudBees/src/main.php diff --git a/src/Flagd/phpcs.xml.dist b/providers/CloudBees/phpcs.xml.dist similarity index 100% rename from src/Flagd/phpcs.xml.dist rename to providers/CloudBees/phpcs.xml.dist diff --git a/src/Split/phpstan.neon.dist b/providers/CloudBees/phpstan.neon.dist similarity index 100% rename from src/Split/phpstan.neon.dist rename to providers/CloudBees/phpstan.neon.dist diff --git a/src/Split/phpunit.xml.dist b/providers/CloudBees/phpunit.xml.dist similarity index 100% rename from src/Split/phpunit.xml.dist rename to providers/CloudBees/phpunit.xml.dist diff --git a/src/Flagd/psalm-baseline.xml b/providers/CloudBees/psalm-baseline.xml similarity index 100% rename from src/Flagd/psalm-baseline.xml rename to providers/CloudBees/psalm-baseline.xml diff --git a/src/Split/psalm.xml b/providers/CloudBees/psalm.xml similarity index 100% rename from src/Split/psalm.xml rename to providers/CloudBees/psalm.xml diff --git a/src/CloudBees/release-please-config.json b/providers/CloudBees/release-please-config.json similarity index 100% rename from src/CloudBees/release-please-config.json rename to providers/CloudBees/release-please-config.json diff --git a/src/CloudBees/scripts/scaffold-integration-tests.py b/providers/CloudBees/scripts/scaffold-integration-tests.py similarity index 100% rename from src/CloudBees/scripts/scaffold-integration-tests.py rename to providers/CloudBees/scripts/scaffold-integration-tests.py diff --git a/src/CloudBees/scripts/seed-data.json b/providers/CloudBees/scripts/seed-data.json similarity index 100% rename from src/CloudBees/scripts/seed-data.json rename to providers/CloudBees/scripts/seed-data.json diff --git a/src/CloudBees/src/CloudBeesProvider.php b/providers/CloudBees/src/CloudBeesProvider.php similarity index 100% rename from src/CloudBees/src/CloudBeesProvider.php rename to providers/CloudBees/src/CloudBeesProvider.php diff --git a/src/CloudBees/src/context/ContextAdapter.php b/providers/CloudBees/src/context/ContextAdapter.php similarity index 100% rename from src/CloudBees/src/context/ContextAdapter.php rename to providers/CloudBees/src/context/ContextAdapter.php diff --git a/src/CloudBees/src/errors/InvalidJsonTypeException.php b/providers/CloudBees/src/errors/InvalidJsonTypeException.php similarity index 100% rename from src/CloudBees/src/errors/InvalidJsonTypeException.php rename to providers/CloudBees/src/errors/InvalidJsonTypeException.php diff --git a/src/CloudBees/src/errors/JsonParseException.php b/providers/CloudBees/src/errors/JsonParseException.php similarity index 100% rename from src/CloudBees/src/errors/JsonParseException.php rename to providers/CloudBees/src/errors/JsonParseException.php diff --git a/src/CloudBees/src/transformers/IdentityTransformer.php b/providers/CloudBees/src/transformers/IdentityTransformer.php similarity index 100% rename from src/CloudBees/src/transformers/IdentityTransformer.php rename to providers/CloudBees/src/transformers/IdentityTransformer.php diff --git a/src/CloudBees/src/transformers/JsonTransformer.php b/providers/CloudBees/src/transformers/JsonTransformer.php similarity index 100% rename from src/CloudBees/src/transformers/JsonTransformer.php rename to providers/CloudBees/src/transformers/JsonTransformer.php diff --git a/src/CloudBees/tests/TestCase.php b/providers/CloudBees/tests/TestCase.php similarity index 100% rename from src/CloudBees/tests/TestCase.php rename to providers/CloudBees/tests/TestCase.php diff --git a/src/CloudBees/tests/integration/CloudBeesProviderTest.php b/providers/CloudBees/tests/integration/CloudBeesProviderTest.php similarity index 100% rename from src/CloudBees/tests/integration/CloudBeesProviderTest.php rename to providers/CloudBees/tests/integration/CloudBeesProviderTest.php diff --git a/src/CloudBees/tests/unit/JsonTransformerTest.php b/providers/CloudBees/tests/unit/JsonTransformerTest.php similarity index 100% rename from src/CloudBees/tests/unit/JsonTransformerTest.php rename to providers/CloudBees/tests/unit/JsonTransformerTest.php diff --git a/src/Split/.github/workflows/release-please.yml b/providers/Flagd/.github/workflows/release-please.yml similarity index 100% rename from src/Split/.github/workflows/release-please.yml rename to providers/Flagd/.github/workflows/release-please.yml diff --git a/src/Split/.gitignore b/providers/Flagd/.gitignore similarity index 100% rename from src/Split/.gitignore rename to providers/Flagd/.gitignore diff --git a/src/Split/.release-please-manifest.json b/providers/Flagd/.release-please-manifest.json similarity index 100% rename from src/Split/.release-please-manifest.json rename to providers/Flagd/.release-please-manifest.json diff --git a/src/Flagd/README.md b/providers/Flagd/README.md similarity index 100% rename from src/Flagd/README.md rename to providers/Flagd/README.md diff --git a/src/Flagd/composer.json b/providers/Flagd/composer.json similarity index 100% rename from src/Flagd/composer.json rename to providers/Flagd/composer.json diff --git a/src/Split/examples/.gitignore b/providers/Flagd/examples/.gitignore similarity index 100% rename from src/Split/examples/.gitignore rename to providers/Flagd/examples/.gitignore diff --git a/src/Flagd/examples/Grpc/README.md b/providers/Flagd/examples/Grpc/README.md similarity index 100% rename from src/Flagd/examples/Grpc/README.md rename to providers/Flagd/examples/Grpc/README.md diff --git a/src/Flagd/examples/Grpc/composer.json b/providers/Flagd/examples/Grpc/composer.json similarity index 100% rename from src/Flagd/examples/Grpc/composer.json rename to providers/Flagd/examples/Grpc/composer.json diff --git a/src/Flagd/examples/Grpc/src/main.php b/providers/Flagd/examples/Grpc/src/main.php similarity index 100% rename from src/Flagd/examples/Grpc/src/main.php rename to providers/Flagd/examples/Grpc/src/main.php diff --git a/src/Flagd/examples/Http/README.md b/providers/Flagd/examples/Http/README.md similarity index 100% rename from src/Flagd/examples/Http/README.md rename to providers/Flagd/examples/Http/README.md diff --git a/src/Flagd/examples/Http/composer.json b/providers/Flagd/examples/Http/composer.json similarity index 100% rename from src/Flagd/examples/Http/composer.json rename to providers/Flagd/examples/Http/composer.json diff --git a/src/Flagd/examples/Http/src/main.php b/providers/Flagd/examples/Http/src/main.php similarity index 100% rename from src/Flagd/examples/Http/src/main.php rename to providers/Flagd/examples/Http/src/main.php diff --git a/src/Split/phpcs.xml.dist b/providers/Flagd/phpcs.xml.dist similarity index 100% rename from src/Split/phpcs.xml.dist rename to providers/Flagd/phpcs.xml.dist diff --git a/src/Flagd/phpstan.neon.dist b/providers/Flagd/phpstan.neon.dist similarity index 100% rename from src/Flagd/phpstan.neon.dist rename to providers/Flagd/phpstan.neon.dist diff --git a/src/Flagd/phpunit.xml.dist b/providers/Flagd/phpunit.xml.dist similarity index 100% rename from src/Flagd/phpunit.xml.dist rename to providers/Flagd/phpunit.xml.dist diff --git a/src/Flagd/proto/README.md b/providers/Flagd/proto/README.md similarity index 100% rename from src/Flagd/proto/README.md rename to providers/Flagd/proto/README.md diff --git a/src/Flagd/proto/php/GPBMetadata/Schema/V1/Schema.php b/providers/Flagd/proto/php/GPBMetadata/Schema/V1/Schema.php similarity index 100% rename from src/Flagd/proto/php/GPBMetadata/Schema/V1/Schema.php rename to providers/Flagd/proto/php/GPBMetadata/Schema/V1/Schema.php diff --git a/src/Flagd/proto/php/Schema/V1/EventStreamResponse.php b/providers/Flagd/proto/php/Schema/V1/EventStreamResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/EventStreamResponse.php rename to providers/Flagd/proto/php/Schema/V1/EventStreamResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php rename to providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php rename to providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php rename to providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php rename to providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveIntRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveIntRequest.php rename to providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveIntResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveIntResponse.php rename to providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php rename to providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php rename to providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveStringRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveStringRequest.php rename to providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php diff --git a/src/Flagd/proto/php/Schema/V1/ResolveStringResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ResolveStringResponse.php rename to providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php diff --git a/src/Flagd/proto/php/Schema/V1/ServiceClient.php b/providers/Flagd/proto/php/Schema/V1/ServiceClient.php similarity index 100% rename from src/Flagd/proto/php/Schema/V1/ServiceClient.php rename to providers/Flagd/proto/php/Schema/V1/ServiceClient.php diff --git a/src/Split/psalm-baseline.xml b/providers/Flagd/psalm-baseline.xml similarity index 100% rename from src/Split/psalm-baseline.xml rename to providers/Flagd/psalm-baseline.xml diff --git a/src/Flagd/psalm.xml b/providers/Flagd/psalm.xml similarity index 100% rename from src/Flagd/psalm.xml rename to providers/Flagd/psalm.xml diff --git a/src/Flagd/release-please-config.json b/providers/Flagd/release-please-config.json similarity index 100% rename from src/Flagd/release-please-config.json rename to providers/Flagd/release-please-config.json diff --git a/src/Flagd/schemas b/providers/Flagd/schemas similarity index 100% rename from src/Flagd/schemas rename to providers/Flagd/schemas diff --git a/src/Flagd/src/FlagdProvider.php b/providers/Flagd/src/FlagdProvider.php similarity index 100% rename from src/Flagd/src/FlagdProvider.php rename to providers/Flagd/src/FlagdProvider.php diff --git a/src/Flagd/src/common/EvaluationContextArrayFactory.php b/providers/Flagd/src/common/EvaluationContextArrayFactory.php similarity index 100% rename from src/Flagd/src/common/EvaluationContextArrayFactory.php rename to providers/Flagd/src/common/EvaluationContextArrayFactory.php diff --git a/src/Flagd/src/common/ResponseCodeErrorCodeMap.php b/providers/Flagd/src/common/ResponseCodeErrorCodeMap.php similarity index 100% rename from src/Flagd/src/common/ResponseCodeErrorCodeMap.php rename to providers/Flagd/src/common/ResponseCodeErrorCodeMap.php diff --git a/src/Flagd/src/common/SafeArrayAccessor.php b/providers/Flagd/src/common/SafeArrayAccessor.php similarity index 100% rename from src/Flagd/src/common/SafeArrayAccessor.php rename to providers/Flagd/src/common/SafeArrayAccessor.php diff --git a/src/Flagd/src/config/Config.php b/providers/Flagd/src/config/Config.php similarity index 100% rename from src/Flagd/src/config/Config.php rename to providers/Flagd/src/config/Config.php diff --git a/src/Flagd/src/config/ConfigFactory.php b/providers/Flagd/src/config/ConfigFactory.php similarity index 100% rename from src/Flagd/src/config/ConfigFactory.php rename to providers/Flagd/src/config/ConfigFactory.php diff --git a/src/Flagd/src/config/Defaults.php b/providers/Flagd/src/config/Defaults.php similarity index 100% rename from src/Flagd/src/config/Defaults.php rename to providers/Flagd/src/config/Defaults.php diff --git a/src/Flagd/src/config/HttpConfig.php b/providers/Flagd/src/config/HttpConfig.php similarity index 100% rename from src/Flagd/src/config/HttpConfig.php rename to providers/Flagd/src/config/HttpConfig.php diff --git a/src/Flagd/src/config/IConfig.php b/providers/Flagd/src/config/IConfig.php similarity index 100% rename from src/Flagd/src/config/IConfig.php rename to providers/Flagd/src/config/IConfig.php diff --git a/src/Flagd/src/config/IHttpConfig.php b/providers/Flagd/src/config/IHttpConfig.php similarity index 100% rename from src/Flagd/src/config/IHttpConfig.php rename to providers/Flagd/src/config/IHttpConfig.php diff --git a/src/Flagd/src/config/Protocols.php b/providers/Flagd/src/config/Protocols.php similarity index 100% rename from src/Flagd/src/config/Protocols.php rename to providers/Flagd/src/config/Protocols.php diff --git a/src/Flagd/src/config/Validator.php b/providers/Flagd/src/config/Validator.php similarity index 100% rename from src/Flagd/src/config/Validator.php rename to providers/Flagd/src/config/Validator.php diff --git a/src/Flagd/src/errors/InvalidConfigException.php b/providers/Flagd/src/errors/InvalidConfigException.php similarity index 100% rename from src/Flagd/src/errors/InvalidConfigException.php rename to providers/Flagd/src/errors/InvalidConfigException.php diff --git a/src/Flagd/src/errors/InvalidTypeException.php b/providers/Flagd/src/errors/InvalidTypeException.php similarity index 100% rename from src/Flagd/src/errors/InvalidTypeException.php rename to providers/Flagd/src/errors/InvalidTypeException.php diff --git a/src/Flagd/src/errors/RequestBuildException.php b/providers/Flagd/src/errors/RequestBuildException.php similarity index 100% rename from src/Flagd/src/errors/RequestBuildException.php rename to providers/Flagd/src/errors/RequestBuildException.php diff --git a/src/Flagd/src/grpc/GrpcService.php b/providers/Flagd/src/grpc/GrpcService.php similarity index 100% rename from src/Flagd/src/grpc/GrpcService.php rename to providers/Flagd/src/grpc/GrpcService.php diff --git a/src/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php b/providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php similarity index 100% rename from src/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php rename to providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php diff --git a/src/Flagd/src/grpc/ResponseValidator.php b/providers/Flagd/src/grpc/ResponseValidator.php similarity index 100% rename from src/Flagd/src/grpc/ResponseValidator.php rename to providers/Flagd/src/grpc/ResponseValidator.php diff --git a/src/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php b/providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php similarity index 100% rename from src/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php rename to providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php diff --git a/src/Flagd/src/http/FlagdResponseValidator.php b/providers/Flagd/src/http/FlagdResponseValidator.php similarity index 100% rename from src/Flagd/src/http/FlagdResponseValidator.php rename to providers/Flagd/src/http/FlagdResponseValidator.php diff --git a/src/Flagd/src/http/GrpcWebEndpoint.php b/providers/Flagd/src/http/GrpcWebEndpoint.php similarity index 100% rename from src/Flagd/src/http/GrpcWebEndpoint.php rename to providers/Flagd/src/http/GrpcWebEndpoint.php diff --git a/src/Flagd/src/http/HttpService.php b/providers/Flagd/src/http/HttpService.php similarity index 100% rename from src/Flagd/src/http/HttpService.php rename to providers/Flagd/src/http/HttpService.php diff --git a/src/Flagd/src/http/Method.php b/providers/Flagd/src/http/Method.php similarity index 100% rename from src/Flagd/src/http/Method.php rename to providers/Flagd/src/http/Method.php diff --git a/src/Flagd/src/service/ServiceFactory.php b/providers/Flagd/src/service/ServiceFactory.php similarity index 100% rename from src/Flagd/src/service/ServiceFactory.php rename to providers/Flagd/src/service/ServiceFactory.php diff --git a/src/Flagd/src/service/ServiceInterface.php b/providers/Flagd/src/service/ServiceInterface.php similarity index 100% rename from src/Flagd/src/service/ServiceInterface.php rename to providers/Flagd/src/service/ServiceInterface.php diff --git a/src/Flagd/tests/TestCase.php b/providers/Flagd/tests/TestCase.php similarity index 100% rename from src/Flagd/tests/TestCase.php rename to providers/Flagd/tests/TestCase.php diff --git a/src/Flagd/tests/unit/FlagdProviderTest.php b/providers/Flagd/tests/unit/FlagdProviderTest.php similarity index 100% rename from src/Flagd/tests/unit/FlagdProviderTest.php rename to providers/Flagd/tests/unit/FlagdProviderTest.php diff --git a/providers/Split/.github/workflows/release-please.yml b/providers/Split/.github/workflows/release-please.yml new file mode 100644 index 00000000..93659057 --- /dev/null +++ b/providers/Split/.github/workflows/release-please.yml @@ -0,0 +1,18 @@ +on: + push: + branches: + - main + +name: Run Release Please +jobs: + release-please: + runs-on: ubuntu-latest + + # Release-please creates a PR that tracks all changes + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + command: manifest + token: ${{secrets.GITHUB_TOKEN}} + default-branch: main diff --git a/providers/Split/.gitignore b/providers/Split/.gitignore new file mode 100644 index 00000000..e1efd914 --- /dev/null +++ b/providers/Split/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/vendor +/build \ No newline at end of file diff --git a/providers/Split/.release-please-manifest.json b/providers/Split/.release-please-manifest.json new file mode 100644 index 00000000..1332969b --- /dev/null +++ b/providers/Split/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/src/Split/README.md b/providers/Split/README.md similarity index 100% rename from src/Split/README.md rename to providers/Split/README.md diff --git a/src/Split/composer.json b/providers/Split/composer.json similarity index 100% rename from src/Split/composer.json rename to providers/Split/composer.json diff --git a/providers/Split/examples/.gitignore b/providers/Split/examples/.gitignore new file mode 100644 index 00000000..149cf08d --- /dev/null +++ b/providers/Split/examples/.gitignore @@ -0,0 +1,2 @@ +/*/vendor +/*/composer.lock \ No newline at end of file diff --git a/src/Split/examples/SplitSDK/README.md b/providers/Split/examples/SplitSDK/README.md similarity index 100% rename from src/Split/examples/SplitSDK/README.md rename to providers/Split/examples/SplitSDK/README.md diff --git a/src/Split/examples/SplitSDK/composer.json b/providers/Split/examples/SplitSDK/composer.json similarity index 100% rename from src/Split/examples/SplitSDK/composer.json rename to providers/Split/examples/SplitSDK/composer.json diff --git a/src/Split/examples/SplitSDK/src/main.php b/providers/Split/examples/SplitSDK/src/main.php similarity index 100% rename from src/Split/examples/SplitSDK/src/main.php rename to providers/Split/examples/SplitSDK/src/main.php diff --git a/providers/Split/phpcs.xml.dist b/providers/Split/phpcs.xml.dist new file mode 100644 index 00000000..5ba48465 --- /dev/null +++ b/providers/Split/phpcs.xml.dist @@ -0,0 +1,28 @@ + + + + + + + + ./src + ./tests + + */tests/fixtures/* + */tests/*/fixtures/* + + + + + + + + + + + + + + + + diff --git a/providers/Split/phpstan.neon.dist b/providers/Split/phpstan.neon.dist new file mode 100644 index 00000000..93c5b2d2 --- /dev/null +++ b/providers/Split/phpstan.neon.dist @@ -0,0 +1,9 @@ +parameters: + tmpDir: ./build/cache/phpstan + level: max + paths: + - ./src + - ./tests + excludePaths: + - */tests/fixtures/* + - */tests/*/fixtures/* diff --git a/providers/Split/phpunit.xml.dist b/providers/Split/phpunit.xml.dist new file mode 100644 index 00000000..9d4740e1 --- /dev/null +++ b/providers/Split/phpunit.xml.dist @@ -0,0 +1,28 @@ + + + + + + ./tests/unit + + + ./tests/integration + + + + + + ./src + + + + + + + + diff --git a/providers/Split/psalm-baseline.xml b/providers/Split/psalm-baseline.xml new file mode 100644 index 00000000..ceaa5778 --- /dev/null +++ b/providers/Split/psalm-baseline.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/providers/Split/psalm.xml b/providers/Split/psalm.xml new file mode 100644 index 00000000..c3e6c03c --- /dev/null +++ b/providers/Split/psalm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/providers/Split/release-please-config.json b/providers/Split/release-please-config.json new file mode 100644 index 00000000..5e4bef5f --- /dev/null +++ b/providers/Split/release-please-config.json @@ -0,0 +1,12 @@ +{ + "bootstrap-sha": "a694af0fb48146f386330b446274cc22a432e66d", + "packages": { + ".": { + "release-type": "php", + "prerelease": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-v-in-tag": false + } + } +} \ No newline at end of file diff --git a/src/Split/src/SplitProvider.php b/providers/Split/src/SplitProvider.php similarity index 100% rename from src/Split/src/SplitProvider.php rename to providers/Split/src/SplitProvider.php diff --git a/src/Split/src/errors/InvalidTreatmentTypeException.php b/providers/Split/src/errors/InvalidTreatmentTypeException.php similarity index 100% rename from src/Split/src/errors/InvalidTreatmentTypeException.php rename to providers/Split/src/errors/InvalidTreatmentTypeException.php diff --git a/src/Split/src/errors/SplitFactoryCreationException.php b/providers/Split/src/errors/SplitFactoryCreationException.php similarity index 100% rename from src/Split/src/errors/SplitFactoryCreationException.php rename to providers/Split/src/errors/SplitFactoryCreationException.php diff --git a/src/Split/src/errors/TargetingKeyMissingException.php b/providers/Split/src/errors/TargetingKeyMissingException.php similarity index 100% rename from src/Split/src/errors/TargetingKeyMissingException.php rename to providers/Split/src/errors/TargetingKeyMissingException.php diff --git a/src/Split/src/treatments/TreatmentParser.php b/providers/Split/src/treatments/TreatmentParser.php similarity index 100% rename from src/Split/src/treatments/TreatmentParser.php rename to providers/Split/src/treatments/TreatmentParser.php diff --git a/src/Split/src/treatments/TreatmentValidator.php b/providers/Split/src/treatments/TreatmentValidator.php similarity index 100% rename from src/Split/src/treatments/TreatmentValidator.php rename to providers/Split/src/treatments/TreatmentValidator.php diff --git a/src/Split/tests/TestCase.php b/providers/Split/tests/TestCase.php similarity index 100% rename from src/Split/tests/TestCase.php rename to providers/Split/tests/TestCase.php diff --git a/src/Split/tests/integration/SplitProviderTest.php b/providers/Split/tests/integration/SplitProviderTest.php similarity index 100% rename from src/Split/tests/integration/SplitProviderTest.php rename to providers/Split/tests/integration/SplitProviderTest.php diff --git a/src/Split/tests/integration/files/splits.yml b/providers/Split/tests/integration/files/splits.yml similarity index 100% rename from src/Split/tests/integration/files/splits.yml rename to providers/Split/tests/integration/files/splits.yml diff --git a/src/Split/tests/unit/SplitProviderTest.php b/providers/Split/tests/unit/SplitProviderTest.php similarity index 100% rename from src/Split/tests/unit/SplitProviderTest.php rename to providers/Split/tests/unit/SplitProviderTest.php From a61fe37ef4bf0a44e70d8edfb55650dbba5c9d9c Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 26 Dec 2022 20:31:56 -0500 Subject: [PATCH 04/90] ci: update composer.json for otel hook Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/composer.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json index a3819459..456d2aa8 100644 --- a/hooks/OpenTelemetry/composer.json +++ b/hooks/OpenTelemetry/composer.json @@ -1,14 +1,14 @@ { - "name": "open-feature/split-provider", - "description": "The Split provider package for OpenFeature", + "name": "open-feature/otel-hook", + "description": "The OpenTelemetry hook package for OpenFeature", "license": "Apache-2.0", "type": "library", "keywords": [ "featureflags", "featureflagging", "openfeature", - "split", - "splitio", + "otel", + "opentelemetry", "provider" ], "authors": [ @@ -24,8 +24,7 @@ "require": { "php": "^7.4 || ^8", "open-feature/sdk": "^1.1.0", - "open-telemetry/api": "^0.0.17", - "splitsoftware/split-sdk-php": "^7.1" + "open-telemetry/api": "^0.0.17" }, "require-dev": { "ergebnis/composer-normalize": "^2.25", From ddf01b7262d3d2eca012f9cbe50afb4207563e94 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 26 Dec 2022 20:48:53 -0500 Subject: [PATCH 05/90] ci: configure release-please for otel-hook Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/release-please-config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/OpenTelemetry/release-please-config.json b/hooks/OpenTelemetry/release-please-config.json index 5e4bef5f..5e3fe497 100644 --- a/hooks/OpenTelemetry/release-please-config.json +++ b/hooks/OpenTelemetry/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "a694af0fb48146f386330b446274cc22a432e66d", + "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", "packages": { ".": { "release-type": "php", @@ -9,4 +9,4 @@ "include-v-in-tag": false } } -} \ No newline at end of file +} From 1de8f63a5973984f34f4bc9194d13cac577d33e3 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 26 Dec 2022 21:10:09 -0500 Subject: [PATCH 06/90] chore(otel-hook): add example of manual instrumentation Signed-off-by: Tom Carrio --- .../OTelManualInstrumentation/composer.json | 12 +- .../OTelManualInstrumentation/src/main.php | 171 +++++++++++++++++- 2 files changed, 179 insertions(+), 4 deletions(-) diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json index 7894e958..d0b77990 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json @@ -5,7 +5,7 @@ "license": "Apache-2.0", "autoload": { "psr-4": { - "OpenFeature\\Providers\\Examples\\SplitSdkExample\\": "src/" + "OpenFeature\\Providers\\Examples\\OTelManualInstrumentation\\": "src/" } }, "authors": [ @@ -15,7 +15,13 @@ } ], "require": { - "open-feature/sdk": "^1.1.2", - "open-telemetry/api": "^0.0.17" + "guzzlehttp/guzzle": "*", + "php-http/guzzle7-adapter": "*", + "slim/slim": "~4", + "php-di/php-di": "^6.3", + "php-di/slim-bridge": "^3.2", + "open-telemetry/api": "0.0.17", + "open-telemetry/sdk": "0.0.17", + "open-feature/sdk": "^1.1" } } diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php index 207eebfb..2be1d732 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php @@ -1,3 +1,172 @@ getClient('dev.openfeature.contrib.php', '1.0.0'); + +// Registration of a provider could be done here. See examples from other +// providers in php-sdk-contrib under [the providers directory](https://github.com/open-feature/php-sdk-contrib/tree/main/providers) +$openFeatureApi->setProvider(new NoOpProvider()); + +// The rest of this example code is verbatim copied from OpenTelemetry as +// a demo app which utilizes OTel. We inject a few feature flag lookups +// for demo sake. +$tracerProvider = (new TracerProviderFactory())->create(); +ShutdownHandler::register([$tracerProvider, 'shutdown']); +$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php'); + +$cb = new ContainerBuilder(); +$container = $cb->addDefinitions([ + Tracer::class => $tracer, + Client::class => function () use ($tracer) { + $stack = HandlerStack::create(); + //a guzzle middleware to wrap http calls in a span, and inject trace headers + $stack->push(function (callable $handler) use ($tracer) { + return function (RequestInterface $request, array $options) use ($handler, $tracer): PromiseInterface { + $span = $tracer + ->spanBuilder(sprintf('%s %s', $request->getMethod(), $request->getUri())) + ->setSpanKind(SpanKind::KIND_CLIENT) + ->setAttribute('http.method', $request->getMethod()) + ->setAttribute('http.url', $request->getUri()) + ->startSpan(); + + $ctx = $span->storeInContext(Context::getCurrent()); + $carrier = []; + TraceContextPropagator::getInstance()->inject($carrier, null, $ctx); + //inject traceparent and tracestate headers + foreach ($carrier as $name => $value) { + $request = $request->withAddedHeader($name, $value); + } + + $promise = $handler($request, $options); + $promise->then(function (Response $response) use ($span) { + $span->setAttribute('http.status_code', $response->getStatusCode()) + ->setAttribute('http.response_content_length', $response->getHeaderLine('Content-Length') ?: $response->getBody()->getSize()) + ->setStatus($response->getStatusCode() < 500 ? StatusCode::STATUS_OK : StatusCode::STATUS_ERROR) + ->end(); + + return $response; + }, function (\Throwable $t) use ($span) { + $span->recordException($t)->setStatus(StatusCode::STATUS_ERROR)->end(); + + throw $t; + }); + + return $promise; + }; + }); + + return new Client(['handler' => $stack, 'http_errors' => false]); + }, +])->build(); +$app = Bridge::create($container); + +//middleware starts root span based on route pattern, sets status from http code +$app->add(function (Request $request, RequestHandler $handler) use ($tracer) { + $parent = TraceContextPropagator::getInstance()->extract($request->getHeaders()); + $routeContext = RouteContext::fromRequest($request); + $route = $routeContext->getRoute(); + $root = $tracer->spanBuilder($route->getPattern()) + ->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9)) + ->setParent($parent) + ->setSpanKind(SpanKind::KIND_SERVER) + ->startSpan(); + $scope = $root->activate(); + + try { + $response = $handler->handle($request); + $root->setStatus($response->getStatusCode() < 500 ? StatusCode::STATUS_OK : StatusCode::STATUS_ERROR); + } finally { + $root->end(); + $scope->detach(); + } + + return $response; +}); +$app->addRoutingMiddleware(); +$errorMiddleware = $app->addErrorMiddleware(true, true, true); + +//route for service-one +$app->get('/users/{name}', function ($name, Client $client, Response $response) use ($flagsClient) { + $protocol = $flagsClient->getBooleanValue('dev.openfeature.contrib.php.secure-http-enabled', false, null, null) + ? 'https' + : 'http'; + + $promises = [ + 'two' => $client->getAsync($protocol . '://service-two:8000/two/' . $name), + 'three' => $client->getAsync($protocol . '://service-three:8000/three'), + 'other' => $client->getAsync($protocol . '://httpbin.org/get?foo=bar'), + ]; + $responses = Utils::unwrap($promises); + foreach ($responses as $res) { + $response->getBody()->write($res->getBody()->getContents()); + } + + return $response; +}); + +//route for service-two +$app->get('/two/{name}', function (Response $response, $name) use ($tracer) { + $span = $tracer + ->spanBuilder('get-user') + ->setAttribute('db.system', 'mysql') + ->setAttribute('db.name', 'users') + ->setAttribute('db.user', 'some_user') + ->setAttribute('db.statement', 'select * from users where username = :1') + ->startSpan(); + usleep((int) (0.3 * 1e6)); + $span->setStatus(StatusCode::STATUS_OK)->end(); + $response->getBody()->write(\json_encode(['some' => 'data', 'user' => $name])); + + return $response->withAddedHeader('Content-Type', 'application/json'); +}); + +//route for service-three +$app->get('/three', function (Response $response) use ($flagsClient) { + $waitTime = $flagsClient->getFloatValue('dev.openfeature.contrib.php.three-wait-time', 1e6, null, null); + + usleep((int) (0.2 * $waitTime)); + $response->getBody()->write(\json_encode(['error' => 'foo'])); + + return $response->withStatus(500)->withAddedHeader('Content-Type', 'application/json'); +}); + +$app->run(); +$tracerProvider->shutdown(); From cdad575fd6422e509e72ea07bc60d6310a95a981 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 26 Dec 2022 21:11:08 -0500 Subject: [PATCH 07/90] chore: remove duplicate submodule definition Signed-off-by: Tom Carrio --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4c5f1304..8573d5aa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "schemas"] path = providers/Flagd/schemas url = https://github.com/tcarrio/schemas/ -[submodule "providers/Flagd/schemas"] - path = providers/Flagd/schemas - url = https://github.com/tcarrio/schemas/ From 789a95c47bc278b333bf8b241b0e342baa27acc5 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Tue, 27 Dec 2022 22:23:53 -0500 Subject: [PATCH 08/90] feat(otel-hook): autoload registration of otel hook (#25) * feat(otel-hook): autoload registration of otel hook Signed-off-by: Tom Carrio * test: implement tests and ensure correct handling of global hook state Signed-off-by: Tom Carrio * refactor: simulate autoload via self-documenting method call Signed-off-by: Tom Carrio * test: update to support 7.4+ Signed-off-by: Tom Carrio * docs: info on autoloading in readme Signed-off-by: Tom Carrio * test: always require in test case Signed-off-by: Tom Carrio * test: always assert size 1 Signed-off-by: Tom Carrio * fix: unused imports Signed-off-by: Tom Carrio * refactor: rename test case for autoloading Signed-off-by: Tom Carrio * docs: update all examples and include autoinstrument example Signed-off-by: Tom Carrio * chore: update all open-feature/sdk to 1.2.0 (latest) Signed-off-by: Tom Carrio Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/README.md | 6 +++++ hooks/OpenTelemetry/composer.json | 9 ++++--- .../examples/AutoloadOTelSDK/README.md | 5 ++++ .../examples/AutoloadOTelSDK/composer.json | 16 ++++++++++++ .../examples/AutoloadOTelSDK/src/main.php | 25 +++++++++++++++++++ .../OTelManualInstrumentation/README.md | 2 ++ .../OTelManualInstrumentation/composer.json | 7 +----- .../OTelManualInstrumentation/src/main.php | 2 +- hooks/OpenTelemetry/src/OpenTelemetryHook.php | 19 +++++++++++++- hooks/OpenTelemetry/src/_autoload.php | 6 +++++ .../integration/OpenTelemetryHookTest.php | 23 ++++++++++++++++- providers/CloudBees/composer.json | 2 +- .../examples/CloudBees/composer.json | 2 +- providers/Flagd/examples/Grpc/composer.json | 2 +- providers/Flagd/examples/Http/composer.json | 2 +- providers/Split/composer.json | 2 +- .../Split/examples/SplitSDK/composer.json | 2 +- 17 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md create mode 100644 hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json create mode 100644 hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php create mode 100644 hooks/OpenTelemetry/src/_autoload.php diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md index 67f80885..ee320e9a 100644 --- a/hooks/OpenTelemetry/README.md +++ b/hooks/OpenTelemetry/README.md @@ -12,6 +12,10 @@ OpenTelemetry is an open specification for distributed tracing, metrics, and log This package also builds on various PSRs (PHP Standards Recommendations) such as the Logger interfaces (PSR-3) and the Basic and Extended Coding Standards (PSR-1 and PSR-12). +### Autoloading + +This package supports Composer autoloading. Thus, simply installing the package is all you need in order to immediately get started with OpenTracing for OpenFeature! Examples are provided that showcase the simple setup as well. Check out the Usage section for more info. + ### OpenTelemetry Package Status The OpenTelemetry package for PHP is still in beta, so there could be changes required. However, it exposes global primitives for span retrieval that should not require any configuration upfront for the provider to just work. @@ -37,6 +41,8 @@ OpenTelemetryHook::register(); For more information on OpenTelemetry, check out [their documentation](https://opentelemetry.io/docs/instrumentation/php/). +For more examples, see the [examples](./examples/). + ## Development ### PHP Versioning diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json index 456d2aa8..70a3d219 100644 --- a/hooks/OpenTelemetry/composer.json +++ b/hooks/OpenTelemetry/composer.json @@ -23,7 +23,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.1.0", + "open-feature/sdk": "^1.2.0", "open-telemetry/api": "^0.0.17" }, "require-dev": { @@ -54,7 +54,10 @@ "autoload": { "psr-4": { "OpenFeature\\Hooks\\OpenTelemetry\\": "src" - } + }, + "files": [ + "src/_autoload.php" + ] }, "autoload-dev": { "psr-4": { @@ -109,7 +112,7 @@ "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", "dev:test:integration": [ "@dev:test:integration:setup", - "echo 'No integration tests to run'", + "phpunit --colors=always --testdox --testsuite=integration", "@dev:test:integration:teardown" ], "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md new file mode 100644 index 00000000..6162d7f2 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/README.md @@ -0,0 +1,5 @@ +# OpenFeature OpenTelemetry Hook example + +This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature. + +It showcases the auto-instrumentation functionality of OpenFeature and OpenTelemetry, neither of which requiring imperative interactions with OTel to bootstrap, configure, and utilize it. diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json new file mode 100644 index 00000000..f2116e92 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/composer.json @@ -0,0 +1,16 @@ +{ + "name": "open-feature/otel-manual-instrumentation-example", + "description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation", + "type": "project", + "license": "Apache-2.0", + "authors": [ + { + "name": "Tom Carrio", + "email": "tom@carrio.dev" + } + ], + "require": { + "open-telemetry/api": "0.0.17", + "open-feature/sdk": "^1.2.0" + } +} diff --git a/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php new file mode 100644 index 00000000..a15aa1a3 --- /dev/null +++ b/hooks/OpenTelemetry/examples/AutoloadOTelSDK/src/main.php @@ -0,0 +1,25 @@ +getClient('dev.openfeature.contrib.php.demo', '1.0.0'); + +$version = $client->getStringValue('dev.openfeature.contrib.php.version-value', 'unknown'); + +echo 'Version is ' . $version; \ No newline at end of file diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md index 9e88acd4..b4cfaad7 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/README.md @@ -1,3 +1,5 @@ # OpenFeature OpenTelemetry Hook example This example provides an example of bootstrapping and using the OpenTelemetry hook for OpenFeature. + +It showcases how you can manually configure the OTel SDK for metrics, tracing, and more. This is then utilized under the hood by OpenFeature within its hook lifecycles to report the feature flag semantic events via the tracer. \ No newline at end of file diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json index d0b77990..b1121bbb 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/composer.json @@ -3,11 +3,6 @@ "description": "An example of using the OpenTelemetry hook for OpenFeature with manual instrumentation", "type": "project", "license": "Apache-2.0", - "autoload": { - "psr-4": { - "OpenFeature\\Providers\\Examples\\OTelManualInstrumentation\\": "src/" - } - }, "authors": [ { "name": "Tom Carrio", @@ -22,6 +17,6 @@ "php-di/slim-bridge": "^3.2", "open-telemetry/api": "0.0.17", "open-telemetry/sdk": "0.0.17", - "open-feature/sdk": "^1.1" + "open-feature/sdk": "^1.2.0" } } diff --git a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php index 2be1d732..59ecf457 100644 --- a/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php +++ b/hooks/OpenTelemetry/examples/OTelManualInstrumentation/src/main.php @@ -32,7 +32,7 @@ use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Slim\Routing\RouteContext; -// Registering the OTel hook requires only the following! +// Manually registering the OTel hook requires only the following! // The rest of the work is simply using OpenFeature as you normally would // The current context span will be used to emit trace events. OpenTelemetryHook::register(); diff --git a/hooks/OpenTelemetry/src/OpenTelemetryHook.php b/hooks/OpenTelemetry/src/OpenTelemetryHook.php index 2f215522..790a6c55 100644 --- a/hooks/OpenTelemetry/src/OpenTelemetryHook.php +++ b/hooks/OpenTelemetry/src/OpenTelemetryHook.php @@ -42,7 +42,7 @@ public static function register(): void self::$instance = new OpenTelemetryHook(); } - if (self::$registeredHook) { + if (self::$registeredHook && self::isRegisteredInHooks()) { return; } @@ -88,4 +88,21 @@ public function supportsFlagValueType(string $flagValueType): bool { return true; } + + /** + * Hooks can be cleared by other means so we can't simply memoize whether a registration has occurred + * + * However if no registration has yet happened then we can absolutely determine that the hook will + * not be registered yet. + */ + private static function isRegisteredInHooks(): bool + { + foreach (OpenFeatureAPI::getInstance()->getHooks() as $hook) { + if ($hook instanceof OpenTelemetryHook) { + return true; + } + } + + return false; + } } diff --git a/hooks/OpenTelemetry/src/_autoload.php b/hooks/OpenTelemetry/src/_autoload.php new file mode 100644 index 00000000..69fb8174 --- /dev/null +++ b/hooks/OpenTelemetry/src/_autoload.php @@ -0,0 +1,6 @@ +clearHooks(); + + // When + $this->simulateAutoload(); + + // Then + + $this->assertCount(1, $api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } + public function testCanBeRegistered(): void { // Given $api = OpenFeatureAPI::getInstance(); + $api->clearHooks(); // When OpenTelemetryHook::register(); // Then - $this->assertNotEmpty($api->getHooks()); + $this->assertCount(1, $api->getHooks()); $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); } + + private function simulateAutoload(): void + { + require __DIR__ . '/../../src/_autoload.php'; + } } diff --git a/providers/CloudBees/composer.json b/providers/CloudBees/composer.json index a3f3c6d8..2a306099 100644 --- a/providers/CloudBees/composer.json +++ b/providers/CloudBees/composer.json @@ -24,7 +24,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.0.0", + "open-feature/sdk": "^1.2.0", "rollout/rox": "^5.0" }, "require-dev": { diff --git a/providers/CloudBees/examples/CloudBees/composer.json b/providers/CloudBees/examples/CloudBees/composer.json index 9d2e626d..7ff5ca9e 100644 --- a/providers/CloudBees/examples/CloudBees/composer.json +++ b/providers/CloudBees/examples/CloudBees/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "open-feature/cloudbees-provider": "^0.0.1" } } diff --git a/providers/Flagd/examples/Grpc/composer.json b/providers/Flagd/examples/Grpc/composer.json index fea77ede..15466ff5 100644 --- a/providers/Flagd/examples/Grpc/composer.json +++ b/providers/Flagd/examples/Grpc/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "monolog/monolog": "^2.8" } } diff --git a/providers/Flagd/examples/Http/composer.json b/providers/Flagd/examples/Http/composer.json index 767fed55..317e70d5 100644 --- a/providers/Flagd/examples/Http/composer.json +++ b/providers/Flagd/examples/Http/composer.json @@ -15,6 +15,6 @@ } ], "require": { - "open-feature/sdk": "^0.0.5" + "open-feature/sdk": "^1.2.0" } } diff --git a/providers/Split/composer.json b/providers/Split/composer.json index 3eee1b7f..c0083d01 100644 --- a/providers/Split/composer.json +++ b/providers/Split/composer.json @@ -23,7 +23,7 @@ ], "require": { "php": "^7.4 || ^8", - "open-feature/sdk": "^1.1.0", + "open-feature/sdk": "^1.2.0", "splitsoftware/split-sdk-php": "^7.1" }, "require-dev": { diff --git a/providers/Split/examples/SplitSDK/composer.json b/providers/Split/examples/SplitSDK/composer.json index d5a1f317..8fdcef70 100644 --- a/providers/Split/examples/SplitSDK/composer.json +++ b/providers/Split/examples/SplitSDK/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "open-feature/sdk": "^0.0.5", + "open-feature/sdk": "^1.2.0", "open-feature/split-provider": "^0.0.1" } } From d2b1a0440bbb0d1fa557b3aefd32eee6267f2823 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 28 Dec 2022 00:00:27 -0500 Subject: [PATCH 09/90] feat: dd-trace hook (#26) * feat: dd-trace-hook for Datadog APM Signed-off-by: Tom Carrio * style: apply phpcbf fixes Signed-off-by: Tom Carrio * style: apply fixes for phpstan Signed-off-by: Tom Carrio --- .../.github/workflows/release-please.yml | 18 +++ hooks/DDTrace/.gitignore | 3 + hooks/DDTrace/.release-please-manifest.json | 3 + hooks/DDTrace/README.md | 62 ++++++++ hooks/DDTrace/composer.json | 139 ++++++++++++++++++ hooks/DDTrace/examples/.gitignore | 2 + .../examples/AutoloadDDTrace/README.md | 5 + .../examples/AutoloadDDTrace/composer.json | 16 ++ .../examples/AutoloadDDTrace/src/main.php | 16 ++ hooks/DDTrace/phpcs.xml.dist | 28 ++++ hooks/DDTrace/phpstan.neon.dist | 9 ++ hooks/DDTrace/phpunit.xml.dist | 28 ++++ hooks/DDTrace/psalm-baseline.xml | 2 + hooks/DDTrace/psalm.xml | 17 +++ hooks/DDTrace/release-please-config.json | 12 ++ hooks/DDTrace/src/DDTraceHook.php | 132 +++++++++++++++++ hooks/DDTrace/src/_autoload.php | 6 + hooks/DDTrace/tests/TestCase.php | 40 +++++ .../tests/integration/DDTraceHookTest.php | 47 ++++++ hooks/DDTrace/tests/unit/DDTraceHookTest.php | 26 ++++ 20 files changed, 611 insertions(+) create mode 100644 hooks/DDTrace/.github/workflows/release-please.yml create mode 100644 hooks/DDTrace/.gitignore create mode 100644 hooks/DDTrace/.release-please-manifest.json create mode 100644 hooks/DDTrace/README.md create mode 100644 hooks/DDTrace/composer.json create mode 100644 hooks/DDTrace/examples/.gitignore create mode 100644 hooks/DDTrace/examples/AutoloadDDTrace/README.md create mode 100644 hooks/DDTrace/examples/AutoloadDDTrace/composer.json create mode 100644 hooks/DDTrace/examples/AutoloadDDTrace/src/main.php create mode 100644 hooks/DDTrace/phpcs.xml.dist create mode 100644 hooks/DDTrace/phpstan.neon.dist create mode 100644 hooks/DDTrace/phpunit.xml.dist create mode 100644 hooks/DDTrace/psalm-baseline.xml create mode 100644 hooks/DDTrace/psalm.xml create mode 100644 hooks/DDTrace/release-please-config.json create mode 100644 hooks/DDTrace/src/DDTraceHook.php create mode 100644 hooks/DDTrace/src/_autoload.php create mode 100644 hooks/DDTrace/tests/TestCase.php create mode 100644 hooks/DDTrace/tests/integration/DDTraceHookTest.php create mode 100644 hooks/DDTrace/tests/unit/DDTraceHookTest.php diff --git a/hooks/DDTrace/.github/workflows/release-please.yml b/hooks/DDTrace/.github/workflows/release-please.yml new file mode 100644 index 00000000..93659057 --- /dev/null +++ b/hooks/DDTrace/.github/workflows/release-please.yml @@ -0,0 +1,18 @@ +on: + push: + branches: + - main + +name: Run Release Please +jobs: + release-please: + runs-on: ubuntu-latest + + # Release-please creates a PR that tracks all changes + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + command: manifest + token: ${{secrets.GITHUB_TOKEN}} + default-branch: main diff --git a/hooks/DDTrace/.gitignore b/hooks/DDTrace/.gitignore new file mode 100644 index 00000000..e1efd914 --- /dev/null +++ b/hooks/DDTrace/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/vendor +/build \ No newline at end of file diff --git a/hooks/DDTrace/.release-please-manifest.json b/hooks/DDTrace/.release-please-manifest.json new file mode 100644 index 00000000..1332969b --- /dev/null +++ b/hooks/DDTrace/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/hooks/DDTrace/README.md b/hooks/DDTrace/README.md new file mode 100644 index 00000000..3ecf72b5 --- /dev/null +++ b/hooks/DDTrace/README.md @@ -0,0 +1,62 @@ +# OpenFeature DDTrace Hook + +[![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) +[![Latest Stable Version](http://poser.pugx.org/open-feature/dd-trace-hook/v)](https://packagist.org/packages/open-feature/dd-trace-hook) +[![Total Downloads](http://poser.pugx.org/open-feature/dd-trace-hook/downloads)](https://packagist.org/packages/open-feature/dd-trace-hook) +![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +[![License](http://poser.pugx.org/open-feature/dd-trace-hook/license)](https://packagist.org/packages/open-feature/dd-trace-hook) + +## Overview + +`dd-trace` is the Datadog tracing library for PHP. It is built on the OpenTracing specification. + +This package also builds on various PSRs (PHP Standards Recommendations) such as the Logger interfaces (PSR-3) and the Basic and Extended Coding Standards (PSR-1 and PSR-12). + +### Design + +OpenTracing is now an archived project of the CNCF, with suggestions to move towards DDTrace. Feel free to check out our [DDTrace hook for OpenFeature](../DDTrace/README.md) as well. DDTrace defines a semantic convention for feature flagging which is utilized in this hook to report flag evaluations, which is the basis for the log events being performed in this library for `dd-trace`. + +### Autoloading + +This package supports Composer autoloading. Thus, simply installing the package is all you need in order to immediately get started with Datadog's DDTrace for OpenFeature! Examples are provided that showcase the simple setup as well. Check out the **Usage** section for more info. + +## Installation + +``` +$ composer require open-feature/dd-trace-hook // installs the latest version +``` + +## Usage + +The `DDTraceHook` should be registered to the OpenFeatureAPI globally for use across all evaluations. + +It makes use of the `dd-trace` packages `Globals` utility for current span retrieval, thus has +no dependency on configuration or injection of tracers. + +```php +use OpenFeature\Hooks\DDTrace\DDTraceHook; + +DDTraceHook::register(); +``` + +For more information on DDTrace, check out [their documentation](https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/php?tab=containers). + +For more examples, see the [examples](./examples/). + +## Development + +### PHP Versioning + +This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. + +This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. + +### Installation and Dependencies + +Install dependencies with `composer install`. `composer install` will update the `composer.lock` with the most recent compatible versions. + +We value having as few runtime dependencies as possible. The addition of any dependencies requires careful consideration and review. + +### Testing + +Run tests with `composer run test`. \ No newline at end of file diff --git a/hooks/DDTrace/composer.json b/hooks/DDTrace/composer.json new file mode 100644 index 00000000..57965838 --- /dev/null +++ b/hooks/DDTrace/composer.json @@ -0,0 +1,139 @@ +{ + "name": "open-feature/dd-trace-hook", + "description": "The Datadog dd-trace hook package for OpenFeature", + "license": "Apache-2.0", + "type": "library", + "keywords": [ + "featureflags", + "featureflagging", + "openfeature", + "dd-trace", + "ddtrace", + "datadog", + "provider" + ], + "authors": [ + { + "name": "OpenFeature PHP Maintainers", + "homepage": "https://github.com/orgs/open-feature/teams/php-maintainer" + }, + { + "name": "open-feature/php-sdk-contrib Contributors", + "homepage": "https://github.com/open-feature/php-sdk-contrib/graphs/contributors" + } + ], + "require": { + "php": "^7.4 || ^8", + "open-feature/sdk": "^1.2.0" + }, + "require-dev": { + "datadog/dd-trace": "^0.82.0", + "ergebnis/composer-normalize": "^2.25", + "friendsofphp/php-cs-fixer": "^3.13", + "hamcrest/hamcrest-php": "^2.0", + "mdwheele/zalgo": "^0.3.1", + "mikey179/vfsstream": "v1.6.11", + "mockery/mockery": "^1.5", + "phan/phan": "^5.4", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan-mockery": "^1.0", + "phpstan/phpstan-phpunit": "^1.1", + "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-phpunit": "^0.18.0", + "ramsey/coding-standard": "^2.0.3", + "ramsey/composer-repl": "^1.4", + "ramsey/conventional-commits": "^1.3", + "roave/security-advisories": "dev-latest", + "spatie/phpunit-snapshot-assertions": "^4.2", + "vimeo/psalm": "~4.30.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "OpenFeature\\Hooks\\DDTrace\\": "src" + }, + "files": [ + "src/_autoload.php" + ] + }, + "autoload-dev": { + "psr-4": { + "OpenFeature\\Hooks\\DDTrace\\Test\\": "tests" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "captainhook/plugin-composer": true, + "ramsey/composer-repl": true + }, + "sort-packages": true + }, + "extra": { + "captainhook": { + "force-install": false + } + }, + "scripts": { + "dev:analyze": [ + "@dev:analyze:phpstan", + "@dev:analyze:psalm" + ], + "dev:analyze:phpstan": "phpstan analyse --ansi --debug --memory-limit=512M", + "dev:analyze:psalm": "psalm", + "dev:build:clean": "git clean -fX build/", + "dev:lint": [ + "@dev:lint:syntax", + "@dev:lint:style" + ], + "dev:lint:fix": "phpcbf", + "dev:lint:style": "phpcs --colors", + "dev:lint:syntax": "parallel-lint --colors src/ tests/", + "dev:test": [ + "@dev:lint", + "@dev:analyze", + "@dev:test:unit", + "@dev:test:integration" + ], + "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml", + "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/", + "dev:test:unit": [ + "@dev:test:unit:setup", + "phpunit --colors=always --testdox --testsuite=unit", + "@dev:test:unit:teardown" + ], + "dev:test:unit:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:unit:setup": "echo 'Setup for unit tests...'", + "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", + "dev:test:integration": [ + "@dev:test:integration:setup", + "phpunit --colors=always --testdox --testsuite=integration", + "@dev:test:integration:teardown" + ], + "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:integration:setup": "echo 'Setup for integration tests...'", + "dev:test:integration:teardown": "echo 'Tore down integration tests...'", + "test": "@dev:test" + }, + "scripts-descriptions": { + "dev:analyze": "Runs all static analysis checks.", + "dev:analyze:phpstan": "Runs the PHPStan static analyzer.", + "dev:analyze:psalm": "Runs the Psalm static analyzer.", + "dev:build:clean": "Cleans the build/ directory.", + "dev:lint": "Runs all linting checks.", + "dev:lint:fix": "Auto-fixes coding standards issues, if possible.", + "dev:lint:style": "Checks for coding standards issues.", + "dev:lint:syntax": "Checks for syntax errors.", + "dev:test": "Runs linting, static analysis, and unit tests.", + "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.", + "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.", + "dev:test:unit": "Runs unit tests.", + "test": "Runs linting, static analysis, and unit tests." + } +} diff --git a/hooks/DDTrace/examples/.gitignore b/hooks/DDTrace/examples/.gitignore new file mode 100644 index 00000000..149cf08d --- /dev/null +++ b/hooks/DDTrace/examples/.gitignore @@ -0,0 +1,2 @@ +/*/vendor +/*/composer.lock \ No newline at end of file diff --git a/hooks/DDTrace/examples/AutoloadDDTrace/README.md b/hooks/DDTrace/examples/AutoloadDDTrace/README.md new file mode 100644 index 00000000..f981a28d --- /dev/null +++ b/hooks/DDTrace/examples/AutoloadDDTrace/README.md @@ -0,0 +1,5 @@ +# OpenFeature DDTrace Hook example + +This example provides an example of bootstrapping and using the DDTrace hook for OpenFeature. + +It showcases the auto-instrumentation functionality of OpenFeature and DDTrace, neither of which requiring imperative interactions with DDTrace to bootstrap, configure, and utilize it. diff --git a/hooks/DDTrace/examples/AutoloadDDTrace/composer.json b/hooks/DDTrace/examples/AutoloadDDTrace/composer.json new file mode 100644 index 00000000..e90f37e2 --- /dev/null +++ b/hooks/DDTrace/examples/AutoloadDDTrace/composer.json @@ -0,0 +1,16 @@ +{ + "name": "open-feature/dd-trace-manual-instrumentation-example", + "description": "An example of using the DDTrace hook for OpenFeature with manual instrumentation", + "type": "project", + "license": "Apache-2.0", + "authors": [ + { + "name": "Tom Carrio", + "email": "tom@carrio.dev" + } + ], + "require": { + "open-feature/sdk": "^1.2.0", + "datadog/dd-trace": "^0.82.0" + } +} diff --git a/hooks/DDTrace/examples/AutoloadDDTrace/src/main.php b/hooks/DDTrace/examples/AutoloadDDTrace/src/main.php new file mode 100644 index 00000000..1a8ffa0d --- /dev/null +++ b/hooks/DDTrace/examples/AutoloadDDTrace/src/main.php @@ -0,0 +1,16 @@ +getClient('dev.openfeature.contrib.php.demo', '1.0.0'); + +$version = $client->getStringValue('dev.openfeature.contrib.php.version-value', 'unknown'); + +echo 'Version is ' . $version; \ No newline at end of file diff --git a/hooks/DDTrace/phpcs.xml.dist b/hooks/DDTrace/phpcs.xml.dist new file mode 100644 index 00000000..5ba48465 --- /dev/null +++ b/hooks/DDTrace/phpcs.xml.dist @@ -0,0 +1,28 @@ + + + + + + + + ./src + ./tests + + */tests/fixtures/* + */tests/*/fixtures/* + + + + + + + + + + + + + + + + diff --git a/hooks/DDTrace/phpstan.neon.dist b/hooks/DDTrace/phpstan.neon.dist new file mode 100644 index 00000000..93c5b2d2 --- /dev/null +++ b/hooks/DDTrace/phpstan.neon.dist @@ -0,0 +1,9 @@ +parameters: + tmpDir: ./build/cache/phpstan + level: max + paths: + - ./src + - ./tests + excludePaths: + - */tests/fixtures/* + - */tests/*/fixtures/* diff --git a/hooks/DDTrace/phpunit.xml.dist b/hooks/DDTrace/phpunit.xml.dist new file mode 100644 index 00000000..9d4740e1 --- /dev/null +++ b/hooks/DDTrace/phpunit.xml.dist @@ -0,0 +1,28 @@ + + + + + + ./tests/unit + + + ./tests/integration + + + + + + ./src + + + + + + + + diff --git a/hooks/DDTrace/psalm-baseline.xml b/hooks/DDTrace/psalm-baseline.xml new file mode 100644 index 00000000..ceaa5778 --- /dev/null +++ b/hooks/DDTrace/psalm-baseline.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/hooks/DDTrace/psalm.xml b/hooks/DDTrace/psalm.xml new file mode 100644 index 00000000..c3e6c03c --- /dev/null +++ b/hooks/DDTrace/psalm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/hooks/DDTrace/release-please-config.json b/hooks/DDTrace/release-please-config.json new file mode 100644 index 00000000..5e3fe497 --- /dev/null +++ b/hooks/DDTrace/release-please-config.json @@ -0,0 +1,12 @@ +{ + "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", + "packages": { + ".": { + "release-type": "php", + "prerelease": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-v-in-tag": false + } + } +} diff --git a/hooks/DDTrace/src/DDTraceHook.php b/hooks/DDTrace/src/DDTraceHook.php new file mode 100644 index 00000000..e1e43f43 --- /dev/null +++ b/hooks/DDTrace/src/DDTraceHook.php @@ -0,0 +1,132 @@ +addHooks(self::$instance); + self::$registeredHook = true; + } + + private static ?DDTraceHook $instance = null; + private static bool $registeredHook = false; + + public function before(HookContext $context, HookHints $hints): ?EvaluationContext + { + return null; + } + + public function after(HookContext $context, ResolutionDetails $details, HookHints $hints): void + { + $span = self::getCurrentSpan(); + if (!$span) { + return; + } + + $span->log([ + Tag::LOG_MESSAGE => [ + self::FLAG_KEY => $context->getFlagKey(), + self::FLAG_PROVIDER_NAME => OpenFeatureAPI::getInstance()->getProvider()->getMetadata()->getName(), + self::FLAG_VARIANT => $details->getVariant(), + ], + ], new DateTimeImmutable('now')); + } + + public function error(HookContext $context, Throwable $error, HookHints $hints): void + { + $span = self::getCurrentSpan(); + if (!$span) { + return; + } + + $span->log([ + Tag::LOG_ERROR_OBJECT => [ + self::FLAG_KEY => $context->getFlagKey(), + self::FLAG_PROVIDER_NAME => OpenFeatureAPI::getInstance()->getProvider()->getMetadata()->getName(), + ], + ], new DateTimeImmutable('now')); + } + + public function finally(HookContext $context, HookHints $hints): void + { + // no-op + } + + public function supportsFlagValueType(string $flagValueType): bool + { + return true; + } + + /** + * Hooks can be cleared by other means so we can't simply memoize whether a registration has occurred + * + * However if no registration has yet happened then we can absolutely determine that the hook will + * not be registered yet. + */ + private static function isRegisteredInHooks(): bool + { + foreach (OpenFeatureAPI::getInstance()->getHooks() as $hook) { + if ($hook instanceof DDTraceHook) { + return true; + } + } + + return false; + } + + private static function getCurrentSpan(): ?Span + { + if (!class_exists(GlobalTracer::class)) { + return null; + } + + return GlobalTracer::get()->getActiveSpan(); + } +} diff --git a/hooks/DDTrace/src/_autoload.php b/hooks/DDTrace/src/_autoload.php new file mode 100644 index 00000000..64da5504 --- /dev/null +++ b/hooks/DDTrace/src/_autoload.php @@ -0,0 +1,6 @@ + $class + * @param mixed ...$arguments + * + * @return T & MockInterface + * + * @template T + * + * phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function mockery(string $class, ...$arguments) + { + /** @var T & MockInterface $mock */ + $mock = Mockery::mock($class, ...$arguments); + + return $mock; + } +} diff --git a/hooks/DDTrace/tests/integration/DDTraceHookTest.php b/hooks/DDTrace/tests/integration/DDTraceHookTest.php new file mode 100644 index 00000000..b5fe9e04 --- /dev/null +++ b/hooks/DDTrace/tests/integration/DDTraceHookTest.php @@ -0,0 +1,47 @@ +clearHooks(); + + // When + $this->simulateAutoload(); + + // Then + + $this->assertCount(1, $api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } + + public function testCanBeRegistered(): void + { + // Given + $api = OpenFeatureAPI::getInstance(); + $api->clearHooks(); + + // When + DDTraceHook::register(); + + // Then + $this->assertCount(1, $api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } + + private function simulateAutoload(): void + { + require __DIR__ . '/../../src/_autoload.php'; + } +} diff --git a/hooks/DDTrace/tests/unit/DDTraceHookTest.php b/hooks/DDTrace/tests/unit/DDTraceHookTest.php new file mode 100644 index 00000000..f335328b --- /dev/null +++ b/hooks/DDTrace/tests/unit/DDTraceHookTest.php @@ -0,0 +1,26 @@ +assertNotEmpty($api->getHooks()); + $this->assertInstanceOf(Hook::class, $api->getHooks()[0]); + } +} From ec65d9bf6fffebe92490031239d25d319b9908ef Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 28 Dec 2022 00:02:23 -0500 Subject: [PATCH 10/90] ci: gitsplit for dd-trace-hook Signed-off-by: Tom Carrio --- .gitsplit.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitsplit.yml b/.gitsplit.yml index 9318e9e3..4c5e4013 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -8,6 +8,8 @@ project_url: "https://github.com/open-feature/php-sdk-contrib.git" splits: - prefix: "hooks/OpenTelemetry" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/otel-hook.git" + - prefix: "hooks/DDTrace" + target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/dd-trace-hook.git" - prefix: "providers/Flagd" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/flagd-provider.git" - prefix: "providers/Split" From d30c184ce3819f69cca3a78014061e8d4515a320 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 28 Dec 2022 00:03:48 -0500 Subject: [PATCH 11/90] ci: configure root commit for dd-trace-hook split repo Signed-off-by: Tom Carrio --- hooks/DDTrace/release-please-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/DDTrace/release-please-config.json b/hooks/DDTrace/release-please-config.json index 5e3fe497..0ff7f22c 100644 --- a/hooks/DDTrace/release-please-config.json +++ b/hooks/DDTrace/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", + "bootstrap-sha": "8bad65379d34fb39d3600aeb3c83c5ea684c2180", "packages": { ".": { "release-type": "php", From 5bf9e94d0b4c6e213cd7842f9b352854cde94380 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 28 Dec 2022 00:32:24 -0500 Subject: [PATCH 12/90] docs: add DDTrace to hooks Signed-off-by: Tom Carrio --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 68bd13aa..083e2a15 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ The `php-contrib-sdk` repository is a monorepository containing various provider - [CloudBees](./providers/CloudBees/README.md) - Hooks - [OpenTelemetry](./hooks/OpenTelemetry/README.md) + - [Datadog](./hooks/DDTrace/README.md) ### Status From a326c09b617458aeec91831f327e14fba21bab4e Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Thu, 29 Dec 2022 18:42:44 -0500 Subject: [PATCH 13/90] docs: revert OTel replacements that were correct (#27) Specifically around the Design section, covering the semantic convention for feature flags in OTel. Signed-off-by: Tom Carrio --- hooks/DDTrace/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/DDTrace/README.md b/hooks/DDTrace/README.md index 3ecf72b5..5b20ddad 100644 --- a/hooks/DDTrace/README.md +++ b/hooks/DDTrace/README.md @@ -14,7 +14,7 @@ This package also builds on various PSRs (PHP Standards Recommendations) such as ### Design -OpenTracing is now an archived project of the CNCF, with suggestions to move towards DDTrace. Feel free to check out our [DDTrace hook for OpenFeature](../DDTrace/README.md) as well. DDTrace defines a semantic convention for feature flagging which is utilized in this hook to report flag evaluations, which is the basis for the log events being performed in this library for `dd-trace`. +OpenTracing is now an archived project of the CNCF, with suggestions to move towards OpenTelemetry. Feel free to check out our [OpenTelemetry hook for OpenFeature](../OpenTelemetry/README.md) as well. OpenTelemetry defines a semantic convention for feature flagging which is utilized in this hook to report flag evaluations, which is the basis for the log events being performed in this library for `dd-trace`. ### Autoloading @@ -59,4 +59,4 @@ We value having as few runtime dependencies as possible. The addition of any dep ### Testing -Run tests with `composer run test`. \ No newline at end of file +Run tests with `composer run test`. From a2501e6440e8f25ce3231fffd225f5cf13ab5fe4 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 02:48:11 -0500 Subject: [PATCH 14/90] feat(validators-hook): created new package with validation offering (#30) * feat(validators-hook): created new package with validation offering for OpenFeature hooks Signed-off-by: Tom Carrio * ci: enable testing for Validators Signed-off-by: Tom Carrio * ci: enable testing for DDTrace Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 2 + .gitsplit.yml | 2 + .../.github/workflows/release-please.yml | 18 +++ hooks/Validators/.gitignore | 3 + .../Validators/.release-please-manifest.json | 3 + hooks/Validators/README.md | 67 +++++++++ hooks/Validators/composer.json | 133 ++++++++++++++++++ hooks/Validators/examples/.gitignore | 2 + .../ExampleRegexpValidators/README.md | 3 + .../ExampleRegexpValidators/composer.json | 27 ++++ .../ExampleRegexpValidators/src/main.php | 31 ++++ hooks/Validators/phpcs.xml.dist | 28 ++++ hooks/Validators/phpstan.neon.dist | 9 ++ hooks/Validators/phpunit.xml.dist | 28 ++++ hooks/Validators/psalm-baseline.xml | 2 + hooks/Validators/psalm.xml | 17 +++ hooks/Validators/release-please-config.json | 12 ++ .../src/Exceptions/ValidationException.php | 18 +++ .../InvalidRegularExpressionException.php | 22 +++ .../src/Regexp/RegexpValidatorHook.php | 78 ++++++++++ hooks/Validators/tests/TestCase.php | 40 ++++++ .../integration/RegexpValidatorHookTest.php | 19 +++ .../tests/unit/RegexpValidatorHookTest.php | 111 +++++++++++++++ 23 files changed, 675 insertions(+) create mode 100644 hooks/Validators/.github/workflows/release-please.yml create mode 100644 hooks/Validators/.gitignore create mode 100644 hooks/Validators/.release-please-manifest.json create mode 100644 hooks/Validators/README.md create mode 100644 hooks/Validators/composer.json create mode 100644 hooks/Validators/examples/.gitignore create mode 100644 hooks/Validators/examples/ExampleRegexpValidators/README.md create mode 100644 hooks/Validators/examples/ExampleRegexpValidators/composer.json create mode 100644 hooks/Validators/examples/ExampleRegexpValidators/src/main.php create mode 100644 hooks/Validators/phpcs.xml.dist create mode 100644 hooks/Validators/phpstan.neon.dist create mode 100644 hooks/Validators/phpunit.xml.dist create mode 100644 hooks/Validators/psalm-baseline.xml create mode 100644 hooks/Validators/psalm.xml create mode 100644 hooks/Validators/release-please-config.json create mode 100644 hooks/Validators/src/Exceptions/ValidationException.php create mode 100644 hooks/Validators/src/Regexp/InvalidRegularExpressionException.php create mode 100644 hooks/Validators/src/Regexp/RegexpValidatorHook.php create mode 100644 hooks/Validators/tests/TestCase.php create mode 100644 hooks/Validators/tests/integration/RegexpValidatorHookTest.php create mode 100644 hooks/Validators/tests/unit/RegexpValidatorHookTest.php diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 26f4d021..d6e2b61a 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -15,6 +15,8 @@ jobs: php-version: ['7.4', '8.0', '8.1', '8.2'] project-dir: - hooks/OpenTelemetry + - hooks/DDTrace + - hooks/Validators - providers/Flagd - providers/Split - providers/CloudBees diff --git a/.gitsplit.yml b/.gitsplit.yml index 4c5e4013..ee802707 100644 --- a/.gitsplit.yml +++ b/.gitsplit.yml @@ -10,6 +10,8 @@ splits: target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/otel-hook.git" - prefix: "hooks/DDTrace" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/dd-trace-hook.git" + - prefix: "hooks/Validators" + target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/validators-hook.git" - prefix: "providers/Flagd" target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/flagd-provider.git" - prefix: "providers/Split" diff --git a/hooks/Validators/.github/workflows/release-please.yml b/hooks/Validators/.github/workflows/release-please.yml new file mode 100644 index 00000000..93659057 --- /dev/null +++ b/hooks/Validators/.github/workflows/release-please.yml @@ -0,0 +1,18 @@ +on: + push: + branches: + - main + +name: Run Release Please +jobs: + release-please: + runs-on: ubuntu-latest + + # Release-please creates a PR that tracks all changes + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + command: manifest + token: ${{secrets.GITHUB_TOKEN}} + default-branch: main diff --git a/hooks/Validators/.gitignore b/hooks/Validators/.gitignore new file mode 100644 index 00000000..e1efd914 --- /dev/null +++ b/hooks/Validators/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/vendor +/build \ No newline at end of file diff --git a/hooks/Validators/.release-please-manifest.json b/hooks/Validators/.release-please-manifest.json new file mode 100644 index 00000000..1332969b --- /dev/null +++ b/hooks/Validators/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/hooks/Validators/README.md b/hooks/Validators/README.md new file mode 100644 index 00000000..13a4e2b5 --- /dev/null +++ b/hooks/Validators/README.md @@ -0,0 +1,67 @@ +# OpenFeature Validator Hooks + +[![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) +[![Latest Stable Version](http://poser.pugx.org/open-feature/validators-hook/v)](https://packagist.org/packages/open-feature/validators-hook) +[![Total Downloads](http://poser.pugx.org/open-feature/validators-hook/downloads)](https://packagist.org/packages/open-feature/validators-hook) +![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +[![License](http://poser.pugx.org/open-feature/validators-hook/license)](https://packagist.org/packages/open-feature/validators-hook) + +## Overview + +Validator Hook constructs that provide means to execute validation against resolved feature flag values. + +This package also builds on various PSRs (PHP Standards Recommendations) such as the Logger interfaces (PSR-3) and the Basic and Extended Coding Standards (PSR-1 and PSR-12). + +## Installation + +``` +$ composer require open-feature/validators-hook // installs the latest version +``` + +## Usage + +The following validator hook constructs are available, but more are being worked on over time: + +- `RegexpValidatorHoook` + + +```php +use OpenFeature\Hooks\Validators\RegexpValidatorHook; + +$alphanumericValidator = new RegexpValidatorHook('/^[A-Za-z0-9]+$/'); +$hexadecimalValidator = new RegexpValidatorHook('/^[0-9a-f]+$/'); +$asciiValidator = new RegexpValidatorHook('/^[ -~]$/'); + +// hooks can be applied to the global API, clients, providers, and resolution invocations + +// all feature flag resolutions will use this validator +$api = OpenFeatureAPI::getInstance(); +$api->addHooks($asciiValidator); + +// invocations from this client will use this validator also +$client = $api->getClient('example'); +$client->setHooks([$alphanumericValidator]); + +// this specific invocation will use this validator also +$client->resolveBooleanValue('test-flag', 'deadbeef', null, new EvaluationOptions([$hexadecimalValidator])); +``` + +For more examples, see the [examples](./examples/). + +## Development + +### PHP Versioning + +This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. + +This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. + +### Installation and Dependencies + +Install dependencies with `composer install`. `composer install` will update the `composer.lock` with the most recent compatible versions. + +We value having as few runtime dependencies as possible. The addition of any dependencies requires careful consideration and review. + +### Testing + +Run tests with `composer run test`. \ No newline at end of file diff --git a/hooks/Validators/composer.json b/hooks/Validators/composer.json new file mode 100644 index 00000000..6864239f --- /dev/null +++ b/hooks/Validators/composer.json @@ -0,0 +1,133 @@ +{ + "name": "open-feature/validators-hook", + "description": "A validator hooks package for OpenFeature", + "license": "Apache-2.0", + "type": "library", + "keywords": [ + "featureflags", + "featureflagging", + "openfeature", + "validator", + "hook" + ], + "authors": [ + { + "name": "OpenFeature PHP Maintainers", + "homepage": "https://github.com/orgs/open-feature/teams/php-maintainer" + }, + { + "name": "open-feature/php-sdk-contrib Contributors", + "homepage": "https://github.com/open-feature/php-sdk-contrib/graphs/contributors" + } + ], + "require": { + "php": "^7.4 || ^8", + "open-feature/sdk": "^1.2.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.25", + "friendsofphp/php-cs-fixer": "^3.13", + "hamcrest/hamcrest-php": "^2.0", + "mdwheele/zalgo": "^0.3.1", + "mikey179/vfsstream": "v1.6.11", + "mockery/mockery": "^1.5", + "phan/phan": "^5.4", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan-mockery": "^1.0", + "phpstan/phpstan-phpunit": "^1.1", + "psalm/plugin-mockery": "^0.9.1", + "psalm/plugin-phpunit": "^0.18.0", + "ramsey/coding-standard": "^2.0.3", + "ramsey/composer-repl": "^1.4", + "ramsey/conventional-commits": "^1.3", + "roave/security-advisories": "dev-latest", + "spatie/phpunit-snapshot-assertions": "^4.2", + "vimeo/psalm": "~4.30.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "OpenFeature\\Hooks\\Validators\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "OpenFeature\\Hooks\\Validators\\Test\\": "tests" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "captainhook/plugin-composer": true, + "ramsey/composer-repl": true + }, + "sort-packages": true + }, + "extra": { + "captainhook": { + "force-install": false + } + }, + "scripts": { + "dev:analyze": [ + "@dev:analyze:phpstan", + "@dev:analyze:psalm" + ], + "dev:analyze:phpstan": "phpstan analyse --ansi --debug --memory-limit=512M", + "dev:analyze:psalm": "psalm", + "dev:build:clean": "git clean -fX build/", + "dev:lint": [ + "@dev:lint:syntax", + "@dev:lint:style" + ], + "dev:lint:fix": "phpcbf", + "dev:lint:style": "phpcs --colors", + "dev:lint:syntax": "parallel-lint --colors src/ tests/", + "dev:test": [ + "@dev:lint", + "@dev:analyze", + "@dev:test:unit", + "@dev:test:integration" + ], + "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml", + "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/", + "dev:test:unit": [ + "@dev:test:unit:setup", + "phpunit --colors=always --testdox --testsuite=unit", + "@dev:test:unit:teardown" + ], + "dev:test:unit:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:unit:setup": "echo 'Setup for unit tests...'", + "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", + "dev:test:integration": [ + "@dev:test:integration:setup", + "phpunit --colors=always --testdox --testsuite=integration", + "@dev:test:integration:teardown" + ], + "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:integration:setup": "echo 'Setup for integration tests...'", + "dev:test:integration:teardown": "echo 'Tore down integration tests...'", + "test": "@dev:test" + }, + "scripts-descriptions": { + "dev:analyze": "Runs all static analysis checks.", + "dev:analyze:phpstan": "Runs the PHPStan static analyzer.", + "dev:analyze:psalm": "Runs the Psalm static analyzer.", + "dev:build:clean": "Cleans the build/ directory.", + "dev:lint": "Runs all linting checks.", + "dev:lint:fix": "Auto-fixes coding standards issues, if possible.", + "dev:lint:style": "Checks for coding standards issues.", + "dev:lint:syntax": "Checks for syntax errors.", + "dev:test": "Runs linting, static analysis, and unit tests.", + "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.", + "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.", + "dev:test:unit": "Runs unit tests.", + "test": "Runs linting, static analysis, and unit tests." + } +} diff --git a/hooks/Validators/examples/.gitignore b/hooks/Validators/examples/.gitignore new file mode 100644 index 00000000..149cf08d --- /dev/null +++ b/hooks/Validators/examples/.gitignore @@ -0,0 +1,2 @@ +/*/vendor +/*/composer.lock \ No newline at end of file diff --git a/hooks/Validators/examples/ExampleRegexpValidators/README.md b/hooks/Validators/examples/ExampleRegexpValidators/README.md new file mode 100644 index 00000000..50d8fcc5 --- /dev/null +++ b/hooks/Validators/examples/ExampleRegexpValidators/README.md @@ -0,0 +1,3 @@ +# OpenFeature Validators Hook example + +This example provides an example of using the validators hooks for OpenFeature. diff --git a/hooks/Validators/examples/ExampleRegexpValidators/composer.json b/hooks/Validators/examples/ExampleRegexpValidators/composer.json new file mode 100644 index 00000000..12f72d99 --- /dev/null +++ b/hooks/Validators/examples/ExampleRegexpValidators/composer.json @@ -0,0 +1,27 @@ +{ + "name": "open-feature/validators-hook-example", + "description": "An example of using the validator hooks for OpenFeature", + "type": "project", + "license": "Apache-2.0", + "authors": [ + { + "name": "Tom Carrio", + "email": "tom@carrio.dev" + } + ], + "require": { + "open-feature/sdk": "^1.2.0", + "open-feature/validators-hook": "dev-main" + }, + "repositories": [ + { + "type": "path", + "url": "../../", + "options": { + "versions": { + "open-feature/validators-hook": "dev-main" + } + } + } + ] +} diff --git a/hooks/Validators/examples/ExampleRegexpValidators/src/main.php b/hooks/Validators/examples/ExampleRegexpValidators/src/main.php new file mode 100644 index 00000000..16627b34 --- /dev/null +++ b/hooks/Validators/examples/ExampleRegexpValidators/src/main.php @@ -0,0 +1,31 @@ +getClient('split-example', '1.0'); + +// create some example hook validators + +$alphanumericValidator = new RegexpValidatorHook('/^[A-Za-z0-9]+$/'); +$hexadecimalValidator = new RegexpValidatorHook('/^[0-9a-f]+$/'); +$asciiValidator = new RegexpValidatorHook('/^[ -~]$/'); + +$client->setHooks([ + $alphanumericValidator, + $hexadecimalValidator, + $asciiValidator +]); + +$flagValue = $client->getBooleanDetails('dev.openfeature.example_flag', true, null, null); diff --git a/hooks/Validators/phpcs.xml.dist b/hooks/Validators/phpcs.xml.dist new file mode 100644 index 00000000..5ba48465 --- /dev/null +++ b/hooks/Validators/phpcs.xml.dist @@ -0,0 +1,28 @@ + + + + + + + + ./src + ./tests + + */tests/fixtures/* + */tests/*/fixtures/* + + + + + + + + + + + + + + + + diff --git a/hooks/Validators/phpstan.neon.dist b/hooks/Validators/phpstan.neon.dist new file mode 100644 index 00000000..93c5b2d2 --- /dev/null +++ b/hooks/Validators/phpstan.neon.dist @@ -0,0 +1,9 @@ +parameters: + tmpDir: ./build/cache/phpstan + level: max + paths: + - ./src + - ./tests + excludePaths: + - */tests/fixtures/* + - */tests/*/fixtures/* diff --git a/hooks/Validators/phpunit.xml.dist b/hooks/Validators/phpunit.xml.dist new file mode 100644 index 00000000..9d4740e1 --- /dev/null +++ b/hooks/Validators/phpunit.xml.dist @@ -0,0 +1,28 @@ + + + + + + ./tests/unit + + + ./tests/integration + + + + + + ./src + + + + + + + + diff --git a/hooks/Validators/psalm-baseline.xml b/hooks/Validators/psalm-baseline.xml new file mode 100644 index 00000000..ceaa5778 --- /dev/null +++ b/hooks/Validators/psalm-baseline.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/hooks/Validators/psalm.xml b/hooks/Validators/psalm.xml new file mode 100644 index 00000000..c3e6c03c --- /dev/null +++ b/hooks/Validators/psalm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/hooks/Validators/release-please-config.json b/hooks/Validators/release-please-config.json new file mode 100644 index 00000000..5e3fe497 --- /dev/null +++ b/hooks/Validators/release-please-config.json @@ -0,0 +1,12 @@ +{ + "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", + "packages": { + ".": { + "release-type": "php", + "prerelease": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-v-in-tag": false + } + } +} diff --git a/hooks/Validators/src/Exceptions/ValidationException.php b/hooks/Validators/src/Exceptions/ValidationException.php new file mode 100644 index 00000000..285236c7 --- /dev/null +++ b/hooks/Validators/src/Exceptions/ValidationException.php @@ -0,0 +1,18 @@ +regexp = self::validateRegexp($regexp); + } + + public function before(HookContext $context, HookHints $hints): ?EvaluationContext + { + return null; + } + + public function after(HookContext $context, ResolutionDetails $details, HookHints $hints): void + { + /** @var string $resolvedValue */ + $resolvedValue = $details->getValue(); + + if ($this->testResolvedValue($resolvedValue)) { + return; + } + + throw new ValidationException(); + } + + public function error(HookContext $context, Throwable $error, HookHints $hints): void + { + // no-op + } + + public function finally(HookContext $context, HookHints $hints): void + { + // no-op + } + + public function supportsFlagValueType(string $flagValueType): bool + { + return $flagValueType === FlagValueType::STRING; + } + + private function testResolvedValue(string $resolvedValue): bool + { + return preg_match($this->regexp, $resolvedValue) === 1; + } + + private static function validateRegexp(string $regexp): string + { + if (self::isValidRegexp($regexp)) { + return $regexp; + } + + throw new InvalidRegularExpressionException($regexp); + } + + private static function isValidRegexp(string $regexp): bool + { + return is_int(@preg_match($regexp, '')); + } +} diff --git a/hooks/Validators/tests/TestCase.php b/hooks/Validators/tests/TestCase.php new file mode 100644 index 00000000..584c5e69 --- /dev/null +++ b/hooks/Validators/tests/TestCase.php @@ -0,0 +1,40 @@ + $class + * @param mixed ...$arguments + * + * @return T & MockInterface + * + * @template T + * + * phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function mockery(string $class, ...$arguments) + { + /** @var T & MockInterface $mock */ + $mock = Mockery::mock($class, ...$arguments); + + return $mock; + } +} diff --git a/hooks/Validators/tests/integration/RegexpValidatorHookTest.php b/hooks/Validators/tests/integration/RegexpValidatorHookTest.php new file mode 100644 index 00000000..d174818d --- /dev/null +++ b/hooks/Validators/tests/integration/RegexpValidatorHookTest.php @@ -0,0 +1,19 @@ +assertInstanceOf(Hook::class, $hook); + } +} diff --git a/hooks/Validators/tests/unit/RegexpValidatorHookTest.php b/hooks/Validators/tests/unit/RegexpValidatorHookTest.php new file mode 100644 index 00000000..a1caa6de --- /dev/null +++ b/hooks/Validators/tests/unit/RegexpValidatorHookTest.php @@ -0,0 +1,111 @@ +assertInstanceOf(Hook::class, $hook); + } + + public function testCannotCreateInvalidRegexpForHook(): void + { + $this->expectException(InvalidRegularExpressionException::class); + + new RegexpValidatorHook('/[\\]/'); + } + + public function testAlphanumericRegexpHookPasses(): void + { + $hook = new RegexpValidatorHook('/^[A-Za-z0-9]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->executeHook($hook, 'Abc123'); + } + + public function testAlphanumericRegexpHookFails(): void + { + $hook = new RegexpValidatorHook('/^[A-Za-z0-9]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->expectException(ValidationException::class); + + $this->executeHook($hook, 'This, a sentence, has other invalid characters.'); + } + + public function testHexadecimalRegexpHookPasses(): void + { + $hook = new RegexpValidatorHook('/^[0-9a-f]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->executeHook($hook, 'deadbeef007'); + } + + public function testHexadecimalRegexpHookFails(): void + { + $hook = new RegexpValidatorHook('/^[0-9a-f]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->expectException(ValidationException::class); + + $this->executeHook($hook, '0123456789abcdefg'); + } + + public function testAsciiRegexpHookPasses(): void + { + $hook = new RegexpValidatorHook('/^[ -~]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->executeHook($hook, 'Only ASCII characters get used here: See?'); + } + + public function testAsciiRegexpHookFails(): void + { + $hook = new RegexpValidatorHook('/^[ -~]+$/'); + + $this->assertInstanceOf(Hook::class, $hook); + + $this->expectException(ValidationException::class); + + $this->executeHook($hook, '死'); + } + + private function executeHook(Hook $hook, string $resolvedValue): void + { + $ctx = HookContextFactory::from( + 'any-key', + FlagValueType::STRING, + 'default-value', + null, + new Metadata('client'), + new Metadata('provider'), + ); + + $details = ResolutionDetailsFactory::fromSuccess($resolvedValue); + + $nullHints = new HookHints(); + + $hook->after($ctx, $details, $nullHints); + } +} From eb35ac1ceba69e89cf728dfa91e1ae5d45fbab89 Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Mon, 2 Jan 2023 10:07:06 -0500 Subject: [PATCH 15/90] Updated Validator Readme Signed-off-by: Michael Beemer --- hooks/Validators/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hooks/Validators/README.md b/hooks/Validators/README.md index 13a4e2b5..e7090548 100644 --- a/hooks/Validators/README.md +++ b/hooks/Validators/README.md @@ -14,15 +14,15 @@ This package also builds on various PSRs (PHP Standards Recommendations) such as ## Installation -``` -$ composer require open-feature/validators-hook // installs the latest version +```sh +composer require open-feature/validators-hook ``` ## Usage The following validator hook constructs are available, but more are being worked on over time: -- `RegexpValidatorHoook` +- `RegexpValidatorHook` ```php @@ -64,4 +64,4 @@ We value having as few runtime dependencies as possible. The addition of any dep ### Testing -Run tests with `composer run test`. \ No newline at end of file +Run tests with `composer run test`. From 6de77ff272ebe6821d71c7141f3de1eafabd59ab Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:20:58 -0500 Subject: [PATCH 16/90] docs(validators): remove API/client usage of hook Signed-off-by: Tom Carrio --- hooks/Validators/README.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/hooks/Validators/README.md b/hooks/Validators/README.md index e7090548..b62cb85c 100644 --- a/hooks/Validators/README.md +++ b/hooks/Validators/README.md @@ -32,18 +32,8 @@ $alphanumericValidator = new RegexpValidatorHook('/^[A-Za-z0-9]+$/'); $hexadecimalValidator = new RegexpValidatorHook('/^[0-9a-f]+$/'); $asciiValidator = new RegexpValidatorHook('/^[ -~]$/'); -// hooks can be applied to the global API, clients, providers, and resolution invocations - -// all feature flag resolutions will use this validator -$api = OpenFeatureAPI::getInstance(); -$api->addHooks($asciiValidator); - -// invocations from this client will use this validator also -$client = $api->getClient('example'); -$client->setHooks([$alphanumericValidator]); - -// this specific invocation will use this validator also -$client->resolveBooleanValue('test-flag', 'deadbeef', null, new EvaluationOptions([$hexadecimalValidator])); +// this specific invocation will use this validator +$client->resolveStringValue('test-flag', 'deadbeef', null, new EvaluationOptions([$hexadecimalValidator])); ``` For more examples, see the [examples](./examples/). From 0a04cf34150a3e0c1a5688c3aca80adf839ad68a Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:23:36 -0500 Subject: [PATCH 17/90] docs: make dd-trace-hook install command copyable Signed-off-by: Tom Carrio --- hooks/DDTrace/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/DDTrace/README.md b/hooks/DDTrace/README.md index 5b20ddad..7329fb41 100644 --- a/hooks/DDTrace/README.md +++ b/hooks/DDTrace/README.md @@ -22,8 +22,8 @@ This package supports Composer autoloading. Thus, simply installing the package ## Installation -``` -$ composer require open-feature/dd-trace-hook // installs the latest version +```sh +composer require open-feature/dd-trace-hook // installs the latest version ``` ## Usage From 96bb5fcac387253ad2eab5ce070997ccae5b7c6c Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:24:15 -0500 Subject: [PATCH 18/90] docs: make otel-hook install command copyable Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md index ee320e9a..4f800a82 100644 --- a/hooks/OpenTelemetry/README.md +++ b/hooks/OpenTelemetry/README.md @@ -22,8 +22,8 @@ The OpenTelemetry package for PHP is still in beta, so there could be changes re ## Installation -``` -$ composer require open-feature/otel-hook // installs the latest version +```sh +composer require open-feature/otel-hook // installs the latest version ``` ## Usage @@ -59,4 +59,4 @@ We value having as few runtime dependencies as possible. The addition of any dep ### Testing -Run tests with `composer run test`. \ No newline at end of file +Run tests with `composer run test`. From c26f9ad833bf401177101970cb58b9a2a0ff17d0 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:25:07 -0500 Subject: [PATCH 19/90] docs: make cloudbees-provider install command copyable Signed-off-by: Tom Carrio --- providers/CloudBees/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/providers/CloudBees/README.md b/providers/CloudBees/README.md index 806937bb..6c2dec29 100644 --- a/providers/CloudBees/README.md +++ b/providers/CloudBees/README.md @@ -18,8 +18,8 @@ There is [an open issue](https://github.com/rollout/rox-php/issues/37) with obje ## Installation -``` -$ composer require open-feature/cloudbees-provider // installs the latest version +```sh +composer require open-feature/cloudbees-provider ``` ## Usage @@ -72,4 +72,4 @@ The integration test suite utilizes a locally available mock server for Rollout The docker image is published under `rollout/roxy`. -For more information on Roxy, see [the documentation](https://docs.cloudbees.com/docs/cloudbees-feature-management/latest/debugging/microservices-automated-testing-and-local-development#_running_roxy). \ No newline at end of file +For more information on Roxy, see [the documentation](https://docs.cloudbees.com/docs/cloudbees-feature-management/latest/debugging/microservices-automated-testing-and-local-development#_running_roxy). From 4f02089cf9f1417201f7d6cac473c5643a050be1 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:26:01 -0500 Subject: [PATCH 20/90] docs: make flagd-provider install command copyable Signed-off-by: Tom Carrio --- providers/Flagd/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/providers/Flagd/README.md b/providers/Flagd/README.md index 65196b04..979a9605 100644 --- a/providers/Flagd/README.md +++ b/providers/Flagd/README.md @@ -14,8 +14,8 @@ This package also builds on various PSRs (PHP Standards Recommendations) such as ## Installation -``` -$ composer require open-feature/flagd-provider // installs the latest version +```sh +composer require open-feature/flagd-provider ``` ## Usage @@ -70,4 +70,4 @@ We value having as few runtime dependencies as possible. The addition of any dep ### Testing -Run tests with `composer run test`. \ No newline at end of file +Run tests with `composer run test`. From af945d24126b6d96f843b9fb3e2eaf9648a35e6c Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:26:44 -0500 Subject: [PATCH 21/90] docs: make split-provider install command copyable Signed-off-by: Tom Carrio --- providers/Split/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/providers/Split/README.md b/providers/Split/README.md index aa4faac3..3f06837c 100644 --- a/providers/Split/README.md +++ b/providers/Split/README.md @@ -14,8 +14,8 @@ This package also builds on various PSRs (PHP Standards Recommendations) such as ## Installation -``` -$ composer require open-feature/split-provider // installs the latest version +```sh +composer require open-feature/split-provider ``` ## Usage @@ -95,4 +95,4 @@ We value having as few runtime dependencies as possible. The addition of any dep ### Testing -Run tests with `composer run test`. \ No newline at end of file +Run tests with `composer run test`. From 683708ecaba98b6629a8a0a259ad42e949976b2d Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:27:57 -0500 Subject: [PATCH 22/90] docs: removal invalid comment style from install command Signed-off-by: Tom Carrio --- hooks/DDTrace/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/DDTrace/README.md b/hooks/DDTrace/README.md index 7329fb41..9a1b8401 100644 --- a/hooks/DDTrace/README.md +++ b/hooks/DDTrace/README.md @@ -23,7 +23,7 @@ This package supports Composer autoloading. Thus, simply installing the package ## Installation ```sh -composer require open-feature/dd-trace-hook // installs the latest version +composer require open-feature/dd-trace-hook ``` ## Usage From 534aab01f82e94a8880a307ef6ea87cdf6dc4b8f Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:28:28 -0500 Subject: [PATCH 23/90] docs: remove invalid comment style from install command Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md index 4f800a82..29823f57 100644 --- a/hooks/OpenTelemetry/README.md +++ b/hooks/OpenTelemetry/README.md @@ -23,7 +23,7 @@ The OpenTelemetry package for PHP is still in beta, so there could be changes re ## Installation ```sh -composer require open-feature/otel-hook // installs the latest version +composer require open-feature/otel-hook ``` ## Usage From b87965274ede870f88995bd9907eddeed9d57ccd Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 11:29:47 -0500 Subject: [PATCH 24/90] docs: add Validators to README hooks Signed-off-by: Tom Carrio --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 083e2a15..10f7cf7f 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ The `php-contrib-sdk` repository is a monorepository containing various provider - Hooks - [OpenTelemetry](./hooks/OpenTelemetry/README.md) - [Datadog](./hooks/DDTrace/README.md) + - [Validators](./hooks/Validators/README.md) ### Status From e8e74a0f7a27eff1ffd8745ffb6e0873f850ba59 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 19:47:03 -0500 Subject: [PATCH 25/90] ci: enable codecov (#33) * ci: enable codecov Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index d6e2b61a..8dff30b4 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -82,20 +82,18 @@ jobs: working-directory: ${{ matrix.project-dir }} run: | composer run dev:test:unit:setup - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover --testsuite unit + vendor/bin/phpunit --coverage-text --coverage-clover=coverage.unit.xml --testsuite unit composer run dev:test:unit:teardown - name: Run PHPUnit (integration tests) working-directory: ${{ matrix.project-dir }} run: | composer run dev:test:integration:setup - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover --testsuite integration + vendor/bin/phpunit --coverage-text --coverage-clover=coverage.integration.xml --testsuite integration composer run dev:test:integration:teardown - ### TODO: Enable codecov support - # - name: Code Coverage - # working-directory: ${{ matrix.project-dir }} - # run: bash <(curl -s https://codecov.io/bash) -F ${{ matrix.php-version }} + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 ### TODO: Replicate any necessary package checks # packages: @@ -103,4 +101,4 @@ jobs: # needs: php # with: # matrix_extension: '["ast, json, grpc"]' - # install_directory: '~/.test/.packages' \ No newline at end of file + # install_directory: '~/.test/.packages' From 0fc3c60325927d29bf2962db4099af6197c81b4b Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 19:48:04 -0500 Subject: [PATCH 26/90] docs: add Codecov badge to README Signed-off-by: Tom Carrio --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 10f7cf7f..1f1e7882 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # OpenFeature PHP SDK Contrib Library [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) +[![codecov](https://codecov.io/gh/open-feature/php-sdk-contrib/branch/main/graph/badge.svg?token=3DC5XOEHMY)](https://codecov.io/gh/open-feature/php-sdk-contrib) ![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) ![License](https://img.shields.io/github/license/open-feature/php-sdk-contrib) ![Experimental](https://img.shields.io/badge/Status-Experimental-yellow) From 7d41179677b42e9a9cacbe797fff1773f91a9992 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 20:09:06 -0500 Subject: [PATCH 27/90] chore(flagd): remove gRPC codebase until full implementation (#34) Signed-off-by: Tom Carrio --- providers/Flagd/README.md | 6 +- providers/Flagd/psalm.xml | 2 - providers/Flagd/src/config/Config.php | 2 +- providers/Flagd/src/config/ConfigFactory.php | 2 +- providers/Flagd/src/grpc/GrpcService.php | 161 ------------------ .../grpc/ResponseResolutionDetailsAdapter.php | 53 ------ .../Flagd/src/grpc/ResponseValidator.php | 87 ---------- .../Flagd/src/service/ServiceFactory.php | 4 - 8 files changed, 7 insertions(+), 310 deletions(-) delete mode 100644 providers/Flagd/src/grpc/GrpcService.php delete mode 100644 providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php delete mode 100644 providers/Flagd/src/grpc/ResponseValidator.php diff --git a/providers/Flagd/README.md b/providers/Flagd/README.md index 979a9605..992336fa 100644 --- a/providers/Flagd/README.md +++ b/providers/Flagd/README.md @@ -45,7 +45,7 @@ OpenFeatureAPI::setProvider(new FlagdProvider([ ])); ``` -- **protocol**: "http" | "grpc" _(defaults to http)_ +- **protocol**: "http" _(defaults to http)_ - **host**: string _(defaults to "localhost")_ - **port**: number _(defaults to 8013)_ - **secure**: true | false _(defaults to false)_ @@ -54,6 +54,10 @@ OpenFeatureAPI::setProvider(new FlagdProvider([ - **requestFactory**: a `RequestFactoryInterface` implementation - **streamFactory**: a `StreamFactoryInterface` implementation +### gRPC vs HTTP + +The Flagd server is gRPC but offers gRPC Web endpoints that can be accessed over HTTP. The latter is used by the current implementation of the Flagd provider, with future development planned to implement a gRPC native provider option. There are certain flexibilities around HTTP with PHP available, whereas gRPC is an opinionated code-generation strategy, but they are both useful and gRPC native may provide better performance over certain sync/async scenarios. An additional goal will be to provide benchmarking of the Flagd provider's protocol for various scenarios so this decision can be made more easily by consumers of the provider. + ## Development ### PHP Versioning diff --git a/providers/Flagd/psalm.xml b/providers/Flagd/psalm.xml index f1c9c37a..c3e6c03c 100644 --- a/providers/Flagd/psalm.xml +++ b/providers/Flagd/psalm.xml @@ -11,8 +11,6 @@ - - diff --git a/providers/Flagd/src/config/Config.php b/providers/Flagd/src/config/Config.php index 2638e4d8..639a6ba3 100644 --- a/providers/Flagd/src/config/Config.php +++ b/providers/Flagd/src/config/Config.php @@ -12,7 +12,7 @@ class Config implements IConfig private bool $secure; private ?IHttpConfig $httpConfig; - public function __construct(?string $host = null, ?int $port = null, ?string $protocol = null, ?bool $secure = null, ?IHttpConfig $httpConfig) + public function __construct(?string $host = null, ?int $port = null, ?string $protocol = null, ?bool $secure = null, ?IHttpConfig $httpConfig = null) { $this->host = $host ?? Defaults::DEFAULT_HOST; $this->port = $port ?? Defaults::DEFAULT_PORT; diff --git a/providers/Flagd/src/config/ConfigFactory.php b/providers/Flagd/src/config/ConfigFactory.php index 5baee5f3..674a9349 100644 --- a/providers/Flagd/src/config/ConfigFactory.php +++ b/providers/Flagd/src/config/ConfigFactory.php @@ -6,7 +6,7 @@ class ConfigFactory { - public static function fromOptions(?string $host = null, ?int $port = null, ?string $protocol = null, ?bool $secure = null, ?IHttpConfig $httpConfig): IConfig + public static function fromOptions(?string $host = null, ?int $port = null, ?string $protocol = null, ?bool $secure = null, ?IHttpConfig $httpConfig = null): IConfig { return Validator::validate(new Config($host, $port, $protocol, $secure, $httpConfig)); } diff --git a/providers/Flagd/src/grpc/GrpcService.php b/providers/Flagd/src/grpc/GrpcService.php deleted file mode 100644 index 08bb5b31..00000000 --- a/providers/Flagd/src/grpc/GrpcService.php +++ /dev/null @@ -1,161 +0,0 @@ -getHost(), $config->getPort()); - $secure = $config->isSecure(); - - return new GrpcService($target, $secure); - } - - private ServiceClient $client; - - private function __construct(string $hostname, bool $secure) - { - /** - * @psalm-suppress UndefinedClass - * @var ChannelCredentials $credentials - */ - $credentials = $secure ? ChannelCredentials::createSsl() : ChannelCredentials::createInsecure(); - - $this->client = new ServiceClient($hostname, [ - 'credentials' => $credentials, - ]); - } - - /** - * @param mixed[]|bool|DateTime|float|int|string|null $defaultValue - */ - public function resolveValue(string $flagKey, string $flagType, $defaultValue, ?EvaluationContext $context): ResolutionDetails - { - $methodName = $this->getMethodName($flagType); - $request = $this->getRequestInstance($flagType); - - $request->setFlagKey($flagKey); - $request->setContext($this->buildContextAsStruct($context)); - - /** @var UnaryCall $clientCall */ - $clientCall = $this->client->$methodName($request); - - /** @var mixed $maybeResponse */ - /** @var mixed $status */ - [$maybeResponse, $status] = $clientCall->wait(); - - if (!$this->isSuccessStatus($status)) { - $this->throwForStatus($status); - } - - if (!ResponseValidator::isResponse($maybeResponse)) { - throw new ResolutionError(ErrorCode::PARSE_ERROR(), 'The response type could not be parsed'); - } - - /** @var ResolveBooleanResponse|ResolveFloatResponse|ResolveIntResponse|ResolveObjectResponse|ResolveStringResponse $response */ - $response = $maybeResponse; - - if (!ResponseValidator::isCorrectType($response, $flagType)) { - throw new ResolutionError(ErrorCode::TYPE_MISMATCH(), 'The resolution type is incorrect'); - } - - return ResponseResolutionDetailsAdapter::fromResponse($response); - } - - private function getMethodName(string $flagType): string - { - switch ($flagType) { - case FlagValueType::BOOLEAN: - return 'resolveBoolean'; - case FlagValueType::FLOAT: - return 'resolveFloat'; - case FlagValueType::INTEGER: - return 'resolveInteger'; - case FlagValueType::OBJECT: - return 'resolveObject'; - case FlagValueType::STRING: - return 'resolveString'; - } - - throw new ResolutionError(ErrorCode::GENERAL(), 'Attempted to use invalid flag value type: ' . $flagType); - } - - /** - * @return ResolveBooleanRequest|ResolveFloatRequest|ResolveIntRequest|ResolveObjectRequest|ResolveStringRequest - */ - private function getRequestInstance(string $flagType) - { - switch ($flagType) { - case FlagValueType::BOOLEAN: - return new ResolveBooleanRequest(); - case FlagValueType::FLOAT: - return new ResolveFloatRequest(); - case FlagValueType::INTEGER: - return new ResolveIntRequest(); - case FlagValueType::OBJECT: - return new ResolveObjectRequest(); - case FlagValueType::STRING: - return new ResolveStringRequest(); - } - - throw new ResolutionError(ErrorCode::GENERAL(), 'Attempted to use invalid flag value type: ' . $flagType); - } - - /** - * @param mixed $status - */ - private function isSuccessStatus($status): bool - { - /** - * @psalm-suppress UndefinedConstant - */ - return $status === Grpc\STATUS_OK; - } - - /** - * @param mixed $status - */ - private function throwForStatus($status): void - { - switch ($status) { - default: - throw new ResolutionError(ErrorCode::GENERAL(), 'Error occurred in gRPC call'); - } - } - - private function buildContextAsStruct(?EvaluationContext $context): Struct - { - $contextArray = EvaluationContextArrayFactory::build($context); - - return new Struct($contextArray); - } -} diff --git a/providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php b/providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php deleted file mode 100644 index 541d3666..00000000 --- a/providers/Flagd/src/grpc/ResponseResolutionDetailsAdapter.php +++ /dev/null @@ -1,53 +0,0 @@ -withValue($response['value']) - ->withReason($response['reason']) - ->withVariant($response['variant']) - ->build(); - } - - /** - * @param ResolveBooleanResponse|ResolveFloatResponse|ResolveIntResponse|ResolveObjectResponse|ResolveStringResponse $response - */ - public static function fromResponse($response): ResolutionDetails - { - /** @var bool|int|string|float|Struct $value */ - $value = $response->getValue(); - $reason = $response->getReason(); - $variant = $response->getVariant(); - - if ($value instanceof Struct) { - /** @var mixed[] $value */ - $value = json_decode($value->serializeToJsonString(), true); - } - - return (new ResolutionDetailsBuilder()) - ->withValue($value) - ->withReason($reason) - ->withVariant($variant) - ->build(); - } -} diff --git a/providers/Flagd/src/grpc/ResponseValidator.php b/providers/Flagd/src/grpc/ResponseValidator.php deleted file mode 100644 index deaa4d34..00000000 --- a/providers/Flagd/src/grpc/ResponseValidator.php +++ /dev/null @@ -1,87 +0,0 @@ -getValue(); - - $actualType = self::determineType($value); - - return $expectedType !== $actualType; - } - - /** - * @param mixed $value - */ - private static function determineType($value): string - { - if (is_bool($value)) { - return FlagValueType::BOOLEAN; - } - - if (is_float($value)) { - return FlagValueType::FLOAT; - } - - if (is_int($value)) { - return FlagValueType::INTEGER; - } - - if (is_null($value) || is_array($value)) { - return FlagValueType::OBJECT; - } - - if (is_string($value)) { - return FlagValueType::STRING; - } - - throw new FlagValueTypeError('Unknown'); - } -} diff --git a/providers/Flagd/src/service/ServiceFactory.php b/providers/Flagd/src/service/ServiceFactory.php index 8a8277ab..3917886d 100644 --- a/providers/Flagd/src/service/ServiceFactory.php +++ b/providers/Flagd/src/service/ServiceFactory.php @@ -5,7 +5,6 @@ namespace OpenFeature\Providers\Flagd\service; use OpenFeature\Providers\Flagd\config\IConfig; -use OpenFeature\Providers\Flagd\grpc\GrpcService; use OpenFeature\Providers\Flagd\http\HttpService; class ServiceFactory @@ -13,9 +12,6 @@ class ServiceFactory public static function fromConfig(IConfig $config): ServiceInterface { switch ($config->getProtocol()) { - case 'grpc': - return GrpcService::fromConfig($config); - case 'http': default: return HttpService::fromConfig($config); } From 6e8c9c3e6ceab290f1b20fc481387a1ea32acfc7 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Mon, 2 Jan 2023 20:49:29 -0500 Subject: [PATCH 28/90] ci: release-please otel update (#35) * ci: release-please otel update Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/.release-please-manifest.json | 4 ++-- hooks/OpenTelemetry/release-please-config.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hooks/OpenTelemetry/.release-please-manifest.json b/hooks/OpenTelemetry/.release-please-manifest.json index 1332969b..3a327a03 100644 --- a/hooks/OpenTelemetry/.release-please-manifest.json +++ b/hooks/OpenTelemetry/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" -} \ No newline at end of file + ".": "0.0.3" +} diff --git a/hooks/OpenTelemetry/release-please-config.json b/hooks/OpenTelemetry/release-please-config.json index 5e3fe497..0bb45466 100644 --- a/hooks/OpenTelemetry/release-please-config.json +++ b/hooks/OpenTelemetry/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", + "bootstrap-sha": "61c48c8840a258308dfc24e6ccf8ff73fe1dea6c", "packages": { ".": { "release-type": "php", From 85deeb10a9c0135d15b5135ef58da2fd79a2f6f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 18:40:28 -0500 Subject: [PATCH 29/90] chore(deps): update dependency php to v8.2.1 (#36) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index 24339636..c5277c21 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,4 @@ # php 7.4.33 # php 8.0.24 # php 8.1.11 -php 8.2.0 +php 8.2.1 From 4509d5dc1e9c920035cb5639039b6ecd05c804d7 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sat, 7 Jan 2023 00:34:17 -0500 Subject: [PATCH 30/90] docs: add CONTRIBUTING.md Fixes #29 Signed-off-by: Tom Carrio --- CONTRIBUTING.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..78237dca --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,129 @@ +# Contributing + +## Development + +### System Requirements + +PHP 8+ is recommended. PHP 7.4 is EOL and support will be removed in an upcoming release. + +### Compilation target(s) + +We target compatibility with PHP versions 7.4, 8.0, 8.1, and 8.2. + +### Project Structure + +The repository is made up of two primary directories for development: `hooks` and `providers`. These each contain packages offering OpenFeature Hooks and Providers respectively. All development is done within those packages. + +There is not yet a process for generating a hook or provider package, but [an issue is tracking this](https://github.com/open-feature/php-sdk-contrib/issues/37). + +> **🛈 All of the following instructions are from the context of the package directory being developed.** + +### Installation and Dependencies + +Install dependencies with `composer install`. + +We value having as few runtime dependencies as possible. The addition of any dependencies requires careful consideration and review. + +### Testing + +Run tests with `composer dev:test`. + +All packages should implement `composer` scripts for unit and integration tests. It is fine to provide no-ops for these scripts. + +### Unit tests + +Run unit tests with `composer dev:test:unit`. + +### Integration tests + +Run unit tests with `composer dev:test:unit`. + +### Packaging + +This package is directly available via Packagist and can be installed with `composer require open-feature/sdk`. Packagist utilizes Git and tags for releases, and this process is automated through GitHub. + +## Pull Request + +All contributions to the OpenFeature project are welcome via GitHub pull requests. + +To create a new PR, you will need to first fork the GitHub repository and clone upstream. + +```bash +git clone https://github.com/open-feature/php-sdk-contrib.git openfeature-php-sdk-contrib +``` + +Navigate to the repository folder + +```bash +cd openfeature-php-sdk-contrib +``` + +Add your fork as an origin + +```bash +git remote add fork https://github.com/YOUR_GITHUB_USERNAME/openfeature-php-sdk-contrib.git +``` + +Makes sure your development environment is all setup by building and testing + +```bash +composer install +composer dev:test +``` + +To start working on a new feature or bugfix, create a new branch and start working on it. + +```bash +git checkout -b feat/NAME_OF_FEATURE +# Make your changes +git commit +git push fork feat/NAME_OF_FEATURE +``` + +Open a pull request against the main php-sdk repository. + +### How to Receive Comments + +- If the PR is not ready for review, please mark it as + [`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/). +- Make sure all required CI checks are clear. +- Submit small, focused PRs addressing a single concern/issue. +- Make sure the PR title reflects the contribution. +- Write a summary that helps understand the change. +- Include usage examples in the summary, where applicable. + +### How to Get PRs Merged + +A PR is considered to be **ready to merge** when: + +- Major feedback is resolved. +- Urgent fix can take exception as long as it has been actively communicated. + +Any Maintainer can merge the PR once it is **ready to merge**. Note, that some +PRs may not be merged immediately if the repo is in the process of a release and +the maintainers decided to defer the PR to the next release train. + +If a PR has been stuck (e.g. there are lots of debates and people couldn't agree +on each other), the owner should try to get people aligned by: + +- Consolidating the perspectives and putting a summary in the PR. It is + recommended to add a link into the PR description, which points to a comment + with a summary in the PR conversation. +- Tagging domain experts (by looking at the change history) in the PR asking + for suggestion. +- Reaching out to more people on the [CNCF OpenFeature Slack channel](https://cloud-native.slack.com/archives/C0344AANLA1). +- Stepping back to see if it makes sense to narrow down the scope of the PR or + split it up. +- If none of the above worked and the PR has been stuck for more than 2 weeks, + the owner should bring it to the OpenFeatures [meeting](README.md#contributing). + +## Versioning and releasing + +As described in the [README](./README.md), this project uses release-please, and semantic versioning. +Breaking changes should be identified by using a semantic PR title. + +## Dependencies + +Keep dependencies to a minimum, especially non-dev dependencies. + +The PHP SDK can be a non-dev dependency, as `composer` does not allow multiple versions of packages to be resolved during a `composer install`. From 0210952af1d6774744c633507a9bec73f3cf7251 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 20:37:08 -0500 Subject: [PATCH 31/90] chore!: fix release-please config Signed-off-by: Tom Carrio --- hooks/DDTrace/.release-please-manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/DDTrace/.release-please-manifest.json b/hooks/DDTrace/.release-please-manifest.json index 1332969b..40ff6fe0 100644 --- a/hooks/DDTrace/.release-please-manifest.json +++ b/hooks/DDTrace/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" -} \ No newline at end of file + ".": "0.0.2" +} From 8ee9fe37584ad6754272ad3ac016902e6ebd48d8 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 20:40:34 -0500 Subject: [PATCH 32/90] chore!: fix release-please config (#38) Signed-off-by: Tom Carrio --- hooks/DDTrace/release-please-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/DDTrace/release-please-config.json b/hooks/DDTrace/release-please-config.json index 0ff7f22c..aea7301b 100644 --- a/hooks/DDTrace/release-please-config.json +++ b/hooks/DDTrace/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "8bad65379d34fb39d3600aeb3c83c5ea684c2180", + "bootstrap-sha": "0ccdf98444f440a3ae5799fe9ad624f03e64555c", "packages": { ".": { "release-type": "php", From b452080443d837c66b554b1bb1a07cadba5a152a Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 20:47:20 -0500 Subject: [PATCH 33/90] chore!: reset release-please (#39) Signed-off-by: Tom Carrio --- hooks/OpenTelemetry/.release-please-manifest.json | 2 +- hooks/OpenTelemetry/release-please-config.json | 2 +- hooks/Validators/.release-please-manifest.json | 2 +- hooks/Validators/release-please-config.json | 2 +- providers/CloudBees/.release-please-manifest.json | 2 +- providers/CloudBees/release-please-config.json | 2 +- providers/Flagd/.release-please-manifest.json | 2 +- providers/Flagd/release-please-config.json | 2 +- providers/Split/.release-please-manifest.json | 2 +- providers/Split/release-please-config.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hooks/OpenTelemetry/.release-please-manifest.json b/hooks/OpenTelemetry/.release-please-manifest.json index 3a327a03..63c033ca 100644 --- a/hooks/OpenTelemetry/.release-please-manifest.json +++ b/hooks/OpenTelemetry/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.3" + ".": "0.0.4" } diff --git a/hooks/OpenTelemetry/release-please-config.json b/hooks/OpenTelemetry/release-please-config.json index 0bb45466..c5b169ec 100644 --- a/hooks/OpenTelemetry/release-please-config.json +++ b/hooks/OpenTelemetry/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "61c48c8840a258308dfc24e6ccf8ff73fe1dea6c", + "bootstrap-sha": "0d81790b6c27f1f223d110326756ccf983dd5075", "packages": { ".": { "release-type": "php", diff --git a/hooks/Validators/.release-please-manifest.json b/hooks/Validators/.release-please-manifest.json index 1332969b..c7159c1a 100644 --- a/hooks/Validators/.release-please-manifest.json +++ b/hooks/Validators/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.0.2" } \ No newline at end of file diff --git a/hooks/Validators/release-please-config.json b/hooks/Validators/release-please-config.json index 5e3fe497..84fc6b9b 100644 --- a/hooks/Validators/release-please-config.json +++ b/hooks/Validators/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "0a4beadbad2b40f14063f2ba9bcda258595119e9", + "bootstrap-sha": "5fb24481302981c0821cb031704744ea45be2b1a", "packages": { ".": { "release-type": "php", diff --git a/providers/CloudBees/.release-please-manifest.json b/providers/CloudBees/.release-please-manifest.json index 1332969b..3d2ac0bd 100644 --- a/providers/CloudBees/.release-please-manifest.json +++ b/providers/CloudBees/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.1.0" } \ No newline at end of file diff --git a/providers/CloudBees/release-please-config.json b/providers/CloudBees/release-please-config.json index 4593df0a..c681e38b 100644 --- a/providers/CloudBees/release-please-config.json +++ b/providers/CloudBees/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "55230de0b59fc58a9bf442fdf88356d8ec3e84ac", + "bootstrap-sha": "a9ab81be749ce4872a96ad9ac62cdb96769c28b1", "packages": { ".": { "release-type": "php", diff --git a/providers/Flagd/.release-please-manifest.json b/providers/Flagd/.release-please-manifest.json index 1332969b..10f30916 100644 --- a/providers/Flagd/.release-please-manifest.json +++ b/providers/Flagd/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.2.0" } \ No newline at end of file diff --git a/providers/Flagd/release-please-config.json b/providers/Flagd/release-please-config.json index 760779a7..3deb1399 100644 --- a/providers/Flagd/release-please-config.json +++ b/providers/Flagd/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "5488af04bf743a8d964b2986e8de7183a2ef9350", + "bootstrap-sha": "1ca3951fe67d017f70e4ed0a3e09111b800c100d", "packages": { ".": { "release-type": "php", diff --git a/providers/Split/.release-please-manifest.json b/providers/Split/.release-please-manifest.json index 1332969b..c7159c1a 100644 --- a/providers/Split/.release-please-manifest.json +++ b/providers/Split/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.0.2" } \ No newline at end of file diff --git a/providers/Split/release-please-config.json b/providers/Split/release-please-config.json index 5e4bef5f..0d6e4603 100644 --- a/providers/Split/release-please-config.json +++ b/providers/Split/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "a694af0fb48146f386330b446274cc22a432e66d", + "bootstrap-sha": "bec2ea2f606ebdd93b1b27af10a6a2fffcad7edd", "packages": { ".": { "release-type": "php", From b9a3b7e1017dc56ddfdd767fb8dab2d01b641699 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:05:10 -0500 Subject: [PATCH 34/90] chore!: reset release-please config (#40) Signed-off-by: Tom Carrio --- providers/Split/.release-please-manifest.json | 2 +- providers/Split/release-please-config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/Split/.release-please-manifest.json b/providers/Split/.release-please-manifest.json index c7159c1a..3d2ac0bd 100644 --- a/providers/Split/.release-please-manifest.json +++ b/providers/Split/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.2" + ".": "0.1.0" } \ No newline at end of file diff --git a/providers/Split/release-please-config.json b/providers/Split/release-please-config.json index 0d6e4603..16d04036 100644 --- a/providers/Split/release-please-config.json +++ b/providers/Split/release-please-config.json @@ -1,5 +1,5 @@ { - "bootstrap-sha": "bec2ea2f606ebdd93b1b27af10a6a2fffcad7edd", + "bootstrap-sha": "3590200214fccb0d9408cd6d7ca01674162f88f1", "packages": { ".": { "release-type": "php", From de79e8d5375604f4981cabde01b0a65d8825543c Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:22:07 -0500 Subject: [PATCH 35/90] ci: configure multi-package release-please manifest (#41) --- .release-please-manifest.json | 28 +++++++++++++++++++ hooks/DDTrace/.release-please-manifest.json | 3 -- hooks/DDTrace/release-please-config.json | 12 -------- .../.release-please-manifest.json | 3 -- .../OpenTelemetry/release-please-config.json | 12 -------- .../Validators/.release-please-manifest.json | 3 -- hooks/Validators/release-please-config.json | 12 -------- .../CloudBees/.release-please-manifest.json | 3 -- .../CloudBees/release-please-config.json | 12 -------- providers/Flagd/.release-please-manifest.json | 3 -- providers/Flagd/release-please-config.json | 12 -------- providers/Split/.release-please-manifest.json | 3 -- providers/Split/release-please-config.json | 12 -------- 13 files changed, 28 insertions(+), 90 deletions(-) create mode 100644 .release-please-manifest.json delete mode 100644 hooks/DDTrace/.release-please-manifest.json delete mode 100644 hooks/DDTrace/release-please-config.json delete mode 100644 hooks/OpenTelemetry/.release-please-manifest.json delete mode 100644 hooks/OpenTelemetry/release-please-config.json delete mode 100644 hooks/Validators/.release-please-manifest.json delete mode 100644 hooks/Validators/release-please-config.json delete mode 100644 providers/CloudBees/.release-please-manifest.json delete mode 100644 providers/CloudBees/release-please-config.json delete mode 100644 providers/Flagd/.release-please-manifest.json delete mode 100644 providers/Flagd/release-please-config.json delete mode 100644 providers/Split/.release-please-manifest.json delete mode 100644 providers/Split/release-please-config.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..ef5882a4 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,28 @@ +{ + "packages": { + "hooks/DDTrace": { + "release-as": "0.2.0", + "package-name": "open-feature/dd-trace-hook" + }, + "hooks/OpenTelemetry": { + "release-as": "0.2.0", + "package-name": "open-feature/otel-hook" + }, + "hooks/Validators": { + "release-as": "0.2.0", + "package-name": "open-feature/validators-hook" + }, + "providers/CloudBees": { + "release-as": "0.3.0", + "package-name": "open-feature/cloudbees-provider" + }, + "providers/Flagd": { + "release-as": "0.4.0", + "package-name": "open-feature/flagd-provider" + }, + "providers/Split": { + "release-as": "0.3.0", + "package-name": "open-feature/split-provider" + } + } +} diff --git a/hooks/DDTrace/.release-please-manifest.json b/hooks/DDTrace/.release-please-manifest.json deleted file mode 100644 index 40ff6fe0..00000000 --- a/hooks/DDTrace/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.0.2" -} diff --git a/hooks/DDTrace/release-please-config.json b/hooks/DDTrace/release-please-config.json deleted file mode 100644 index aea7301b..00000000 --- a/hooks/DDTrace/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "0ccdf98444f440a3ae5799fe9ad624f03e64555c", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} diff --git a/hooks/OpenTelemetry/.release-please-manifest.json b/hooks/OpenTelemetry/.release-please-manifest.json deleted file mode 100644 index 63c033ca..00000000 --- a/hooks/OpenTelemetry/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.0.4" -} diff --git a/hooks/OpenTelemetry/release-please-config.json b/hooks/OpenTelemetry/release-please-config.json deleted file mode 100644 index c5b169ec..00000000 --- a/hooks/OpenTelemetry/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "0d81790b6c27f1f223d110326756ccf983dd5075", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} diff --git a/hooks/Validators/.release-please-manifest.json b/hooks/Validators/.release-please-manifest.json deleted file mode 100644 index c7159c1a..00000000 --- a/hooks/Validators/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.0.2" -} \ No newline at end of file diff --git a/hooks/Validators/release-please-config.json b/hooks/Validators/release-please-config.json deleted file mode 100644 index 84fc6b9b..00000000 --- a/hooks/Validators/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "5fb24481302981c0821cb031704744ea45be2b1a", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} diff --git a/providers/CloudBees/.release-please-manifest.json b/providers/CloudBees/.release-please-manifest.json deleted file mode 100644 index 3d2ac0bd..00000000 --- a/providers/CloudBees/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.1.0" -} \ No newline at end of file diff --git a/providers/CloudBees/release-please-config.json b/providers/CloudBees/release-please-config.json deleted file mode 100644 index c681e38b..00000000 --- a/providers/CloudBees/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "a9ab81be749ce4872a96ad9ac62cdb96769c28b1", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} \ No newline at end of file diff --git a/providers/Flagd/.release-please-manifest.json b/providers/Flagd/.release-please-manifest.json deleted file mode 100644 index 10f30916..00000000 --- a/providers/Flagd/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.2.0" -} \ No newline at end of file diff --git a/providers/Flagd/release-please-config.json b/providers/Flagd/release-please-config.json deleted file mode 100644 index 3deb1399..00000000 --- a/providers/Flagd/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "1ca3951fe67d017f70e4ed0a3e09111b800c100d", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} \ No newline at end of file diff --git a/providers/Split/.release-please-manifest.json b/providers/Split/.release-please-manifest.json deleted file mode 100644 index 3d2ac0bd..00000000 --- a/providers/Split/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.1.0" -} \ No newline at end of file diff --git a/providers/Split/release-please-config.json b/providers/Split/release-please-config.json deleted file mode 100644 index 16d04036..00000000 --- a/providers/Split/release-please-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bootstrap-sha": "3590200214fccb0d9408cd6d7ca01674162f88f1", - "packages": { - ".": { - "release-type": "php", - "prerelease": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true, - "include-v-in-tag": false - } - } -} \ No newline at end of file From 39e27042d4f07c40a964dc0211453cbdcb8e6b80 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:29:30 -0500 Subject: [PATCH 36/90] ci: add release-please-config Signed-off-by: Tom Carrio --- .release-please-manifest.json | 30 ++++++------------------------ release-please-config.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 release-please-config.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ef5882a4..6b630aa5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,28 +1,10 @@ { "packages": { - "hooks/DDTrace": { - "release-as": "0.2.0", - "package-name": "open-feature/dd-trace-hook" - }, - "hooks/OpenTelemetry": { - "release-as": "0.2.0", - "package-name": "open-feature/otel-hook" - }, - "hooks/Validators": { - "release-as": "0.2.0", - "package-name": "open-feature/validators-hook" - }, - "providers/CloudBees": { - "release-as": "0.3.0", - "package-name": "open-feature/cloudbees-provider" - }, - "providers/Flagd": { - "release-as": "0.4.0", - "package-name": "open-feature/flagd-provider" - }, - "providers/Split": { - "release-as": "0.3.0", - "package-name": "open-feature/split-provider" - } + "hooks/DDTrace": "0.2.0", + "hooks/OpenTelemetry": "0.2.0", + "hooks/Validators": "0.2.0", + "providers/CloudBees": "0.3.0", + "providers/Flagd": "0.4.0", + "providers/Split": "0.3.0" } } diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..3e2221b3 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,28 @@ +{ + "bootstrap-sha": "91dbcca98f4a56ec37ce1b03bc0f39aeaba6dbd3", + "separate-pull-requests": false, + "prerelease": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-v-in-tag": false, + "packages": { + "hooks/DDTrace": { + "package-name": "open-feature/dd-trace-hook" + }, + "hooks/OpenTelemetry": { + "package-name": "open-feature/otel-hook" + }, + "hooks/Validators": { + "package-name": "open-feature/validators-hook" + }, + "providers/CloudBees": { + "package-name": "open-feature/cloudbees-provider" + }, + "providers/Flagd": { + "package-name": "open-feature/flagd-provider" + }, + "providers/Split": { + "package-name": "open-feature/split-provider" + } + } +} \ No newline at end of file From 25d3907ebe289e6a28707b74574a13959812ce28 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:39:49 -0500 Subject: [PATCH 37/90] ci: enable release-please in root contrib (#42) Signed-off-by: Tom Carrio --- .github/workflows/release-please.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/release-please.yaml diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 00000000..93659057 --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,18 @@ +on: + push: + branches: + - main + +name: Run Release Please +jobs: + release-please: + runs-on: ubuntu-latest + + # Release-please creates a PR that tracks all changes + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + command: manifest + token: ${{secrets.GITHUB_TOKEN}} + default-branch: main From e7ec4c18508f1631ef6d8217d66f35d95e0041d3 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:44:19 -0500 Subject: [PATCH 38/90] ci: release please empty manifest (#43) Signed-off-by: Tom Carrio --- .release-please-manifest.json | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6b630aa5..e69de29b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,10 +0,0 @@ -{ - "packages": { - "hooks/DDTrace": "0.2.0", - "hooks/OpenTelemetry": "0.2.0", - "hooks/Validators": "0.2.0", - "providers/CloudBees": "0.3.0", - "providers/Flagd": "0.4.0", - "providers/Split": "0.3.0" - } -} From 15c97515bc511243327683ab15d8408c16af5976 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:46:19 -0500 Subject: [PATCH 39/90] ci: empty object for release-please manifest (#44) resetting the manifest to let it be configured automatically by release-please going forward Signed-off-by: Tom Carrio --- .release-please-manifest.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e69de29b..69a88e3b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -0,0 +1 @@ +{} From 83977b4f7f99cae61fafd0f3613d21df1d6b8d50 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 21:58:13 -0500 Subject: [PATCH 40/90] ci: set next release versions explicitly (#46) Signed-off-by: Tom Carrio --- release-please-config.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index 3e2221b3..c319cfbb 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -7,22 +7,28 @@ "include-v-in-tag": false, "packages": { "hooks/DDTrace": { - "package-name": "open-feature/dd-trace-hook" + "package-name": "open-feature/dd-trace-hook", + "release-as": "0.2.0" }, "hooks/OpenTelemetry": { - "package-name": "open-feature/otel-hook" + "package-name": "open-feature/otel-hook", + "release-as": "0.2.0" }, "hooks/Validators": { - "package-name": "open-feature/validators-hook" + "package-name": "open-feature/validators-hook", + "release-as": "0.2.0" }, "providers/CloudBees": { - "package-name": "open-feature/cloudbees-provider" + "package-name": "open-feature/cloudbees-provider", + "release-as": "0.3.0" }, "providers/Flagd": { - "package-name": "open-feature/flagd-provider" + "package-name": "open-feature/flagd-provider", + "release-as": "0.4.0" }, "providers/Split": { - "package-name": "open-feature/split-provider" + "package-name": "open-feature/split-provider", + "release-as": "0.3.0" } } } \ No newline at end of file From c9760b4cfe71f0810c297052d72167ad9165ffec Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 8 Jan 2023 22:04:29 -0500 Subject: [PATCH 41/90] ci: packages have separate release PRs (#48) Signed-off-by: Tom Carrio --- release-please-config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index c319cfbb..a7d73257 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,6 +1,6 @@ { "bootstrap-sha": "91dbcca98f4a56ec37ce1b03bc0f39aeaba6dbd3", - "separate-pull-requests": false, + "separate-pull-requests": true, "prerelease": false, "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": true, @@ -31,4 +31,4 @@ "release-as": "0.3.0" } } -} \ No newline at end of file +} From 35d4b5a83a23a18f609f2d184c8250e242845d83 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:06:15 -0500 Subject: [PATCH 42/90] chore(main): release open-feature/flagd-provider 0.4.0 (#49) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- providers/Flagd/CHANGELOG.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 providers/Flagd/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 69a88e3b..5c0889cc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{} +{"providers/Flagd":"0.4.0"} diff --git a/providers/Flagd/CHANGELOG.md b/providers/Flagd/CHANGELOG.md new file mode 100644 index 00000000..c80783a6 --- /dev/null +++ b/providers/Flagd/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## 0.4.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) From 411630e51db13277d00d643a21473a7d58dbd8f4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:07:08 -0500 Subject: [PATCH 43/90] chore(main): release open-feature/split-provider 0.3.0 (#50) Signed-off-by: Tom Carrio Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .release-please-manifest.json | 2 +- providers/Split/CHANGELOG.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 providers/Split/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5c0889cc..5628a2b7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"providers/Flagd":"0.4.0"} +{"providers/Flagd":"0.4.0","providers/Split":"0.3.0} \ No newline at end of file diff --git a/providers/Split/CHANGELOG.md b/providers/Split/CHANGELOG.md new file mode 100644 index 00000000..a0f8406f --- /dev/null +++ b/providers/Split/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +## 0.3.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* reset release-please config ([#40](https://github.com/open-feature/php-sdk-contrib/issues/40)) +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) +* reset release-please config ([#40](https://github.com/open-feature/php-sdk-contrib/issues/40)) ([b9a3b7e](https://github.com/open-feature/php-sdk-contrib/commit/b9a3b7e1017dc56ddfdd767fb8dab2d01b641699)) From 05ce22fec6c39cb21c3aac5cfafd448e66103022 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:08:12 -0500 Subject: [PATCH 44/90] chore(main): release open-feature/cloudbees-provider 0.3.0 (#51) * chore(main): release open-feature/cloudbees-provider 0.3.0 * ci: fix .release-please-manifest.json Signed-off-by: Tom Carrio Signed-off-by: Tom Carrio Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .release-please-manifest.json | 3 ++- providers/CloudBees/CHANGELOG.md | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 providers/CloudBees/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5628a2b7..048714bf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1,2 @@ -{"providers/Flagd":"0.4.0","providers/Split":"0.3.0} \ No newline at end of file +{"providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} + diff --git a/providers/CloudBees/CHANGELOG.md b/providers/CloudBees/CHANGELOG.md new file mode 100644 index 00000000..72863a53 --- /dev/null +++ b/providers/CloudBees/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## 0.3.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) From d07ecd3d1d84c8a2e51b8048d78557bc58c537e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:08:54 -0500 Subject: [PATCH 45/90] chore(main): release open-feature/dd-trace-hook 0.2.0 (#52) Signed-off-by: Tom Carrio Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .release-please-manifest.json | 3 +-- hooks/DDTrace/CHANGELOG.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 hooks/DDTrace/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 048714bf..ccacdcad 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,2 +1 @@ -{"providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} - +{"hooks/DDTrace":"0.2.0","providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} diff --git a/hooks/DDTrace/CHANGELOG.md b/hooks/DDTrace/CHANGELOG.md new file mode 100644 index 00000000..ccb9bb45 --- /dev/null +++ b/hooks/DDTrace/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog + +## 0.2.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* fix release-please config ([#38](https://github.com/open-feature/php-sdk-contrib/issues/38)) +* fix release-please config + +### Features + +* dd-trace hook ([#26](https://github.com/open-feature/php-sdk-contrib/issues/26)) ([d2b1a04](https://github.com/open-feature/php-sdk-contrib/commit/d2b1a0440bbb0d1fa557b3aefd32eee6267f2823)) + + +### Miscellaneous Chores + +* fix release-please config ([0210952](https://github.com/open-feature/php-sdk-contrib/commit/0210952af1d6774744c633507a9bec73f3cf7251)) +* fix release-please config ([#38](https://github.com/open-feature/php-sdk-contrib/issues/38)) ([8ee9fe3](https://github.com/open-feature/php-sdk-contrib/commit/8ee9fe37584ad6754272ad3ac016902e6ebd48d8)) From 94506426081cfe99cbb9be53af1c61e418c70848 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:09:32 -0500 Subject: [PATCH 46/90] chore(main): release open-feature/otel-hook 0.2.0 (#53) Signed-off-by: Tom Carrio Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .release-please-manifest.json | 2 +- hooks/OpenTelemetry/CHANGELOG.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 hooks/OpenTelemetry/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ccacdcad..c3952ca2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{"hooks/DDTrace":"0.2.0","providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} +{"hooks/OpenTelemetry":"0.2.0","hooks/DDTrace":"0.2.0","providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} \ No newline at end of file diff --git a/hooks/OpenTelemetry/CHANGELOG.md b/hooks/OpenTelemetry/CHANGELOG.md new file mode 100644 index 00000000..e1664184 --- /dev/null +++ b/hooks/OpenTelemetry/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## 0.2.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) From f5bb87ba68c9a115188b1187e9c1f585ecd5e3ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:10:48 -0500 Subject: [PATCH 47/90] chore(main): release open-feature/validators-hook 0.2.0 (#54) Signed-off-by: Tom Carrio Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tom Carrio --- .release-please-manifest.json | 9 ++++++++- hooks/Validators/CHANGELOG.md | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 hooks/Validators/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c3952ca2..544118f2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1,8 @@ -{"hooks/OpenTelemetry":"0.2.0","hooks/DDTrace":"0.2.0","providers/CloudBees":"0.3.0","providers/Flagd":"0.4.0","providers/Split":"0.3.0"} \ No newline at end of file +{ + "hooks/DDTrace":"0.2.0", + "hooks/OpenTelemetry":"0.2.0", + "hooks/Validators":"0.2.0", + "providers/CloudBees":"0.3.0", + "providers/Flagd":"0.4.0", + "providers/Split":"0.3.0" +} \ No newline at end of file diff --git a/hooks/Validators/CHANGELOG.md b/hooks/Validators/CHANGELOG.md new file mode 100644 index 00000000..fe7bc168 --- /dev/null +++ b/hooks/Validators/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +## 0.2.0 (2023-01-09) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* **validators-hook:** created new package with validation offering ([#30](https://github.com/open-feature/php-sdk-contrib/issues/30)) ([a2501e6](https://github.com/open-feature/php-sdk-contrib/commit/a2501e6440e8f25ce3231fffd225f5cf13ab5fe4)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) From d028e6d7741d07b7edef21b43b249fdb2d18d8f2 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sat, 11 Feb 2023 22:20:12 -0500 Subject: [PATCH 48/90] feat: deprecate php 7 (#59) * feat!: deprecate PHP 7.4 Signed-off-by: Tom Carrio build: provide a devenv config style: apply linting updates for providers style: apply phpcbf fixes build: disable root-level phpcbf commit hook until configured style: apply linting fixes to Flagd provider refactor: confirm to new provider interface chore: ignore all composer.lock files build!: target new version of open-feature/sdk Signed-off-by: Tom Carrio * feat: deprecate php 7 with full test suite passing Signed-off-by: Tom Carrio --------- Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 2 +- .gitignore | 6 +- .pre-commit-config.yaml | 1 + .tool-versions | 5 +- CONTRIBUTING.md | 4 +- README.md | 6 +- devenv.lock | 152 ++++++++++++++++++ devenv.nix | 52 ++++++ devenv.yaml | 5 + hooks/DDTrace/README.md | 4 +- hooks/DDTrace/composer.json | 4 +- hooks/DDTrace/phpcs.xml.dist | 3 - hooks/OpenTelemetry/README.md | 4 +- hooks/OpenTelemetry/composer.json | 4 +- hooks/OpenTelemetry/phpcs.xml.dist | 3 - hooks/OpenTelemetry/src/TracerHelper.php | 4 +- hooks/Validators/README.md | 4 +- hooks/Validators/composer.json | 4 +- hooks/Validators/phpcs.xml.dist | 3 - providers/CloudBees/README.md | 4 +- providers/CloudBees/composer.json | 4 +- providers/CloudBees/phpcs.xml.dist | 3 - providers/CloudBees/src/CloudBeesProvider.php | 16 +- .../src/transformers/IdentityTransformer.php | 2 +- providers/Flagd/README.md | 4 +- providers/Flagd/composer.json | 4 +- providers/Flagd/phpcs.xml.dist | 3 - providers/Flagd/src/FlagdProvider.php | 10 +- providers/Flagd/src/config/Validator.php | 36 ++--- .../FlagdResponseResolutionDetailsAdapter.php | 8 +- .../Flagd/src/service/ServiceInterface.php | 2 +- providers/Split/README.md | 4 +- providers/Split/composer.json | 4 +- providers/Split/phpcs.xml.dist | 3 - providers/Split/src/SplitProvider.php | 11 +- 35 files changed, 280 insertions(+), 108 deletions(-) create mode 120000 .pre-commit-config.yaml create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 8dff30b4..33cf9c7f 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -12,7 +12,7 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-version: ['7.4', '8.0', '8.1', '8.2'] + php-version: ['8.0', '8.1', '8.2'] project-dir: - hooks/OpenTelemetry - hooks/DDTrace diff --git a/.gitignore b/.gitignore index 4fb5c2ae..b3f34e10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ /captainhook.config.json -/composer.lock +composer.lock /phpcs.xml /phpunit.xml /vendor/ /build/ -/proto/ \ No newline at end of file +/proto/ + +/.devenv* \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 120000 index 00000000..a72a7aff --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +/nix/store/kjn5c8afbhm6xjdaz5z4z2ldwpknw0z9-pre-commit-config.json \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index c5277c21..260a2ddb 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,3 @@ -# php 7.4.33 -# php 8.0.24 +php 8.0.24 # php 8.1.11 -php 8.2.1 +# php 8.2.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 78237dca..2332eb6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,11 @@ ### System Requirements -PHP 8+ is recommended. PHP 7.4 is EOL and support will be removed in an upcoming release. +PHP 8+ is required. ### Compilation target(s) -We target compatibility with PHP versions 7.4, 8.0, 8.1, and 8.2. +We target compatibility with PHP versions 8.0, 8.1, and 8.2. ### Project Structure diff --git a/README.md b/README.md index 1f1e7882..0946782f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![codecov](https://codecov.io/gh/open-feature/php-sdk-contrib/branch/main/graph/badge.svg?token=3DC5XOEHMY)](https://codecov.io/gh/open-feature/php-sdk-contrib) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) ![License](https://img.shields.io/github/license/open-feature/php-sdk-contrib) ![Experimental](https://img.shields.io/badge/Status-Experimental-yellow) @@ -27,9 +27,7 @@ This repository is marked as **experimental** since the repository structure its ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. - -⚠️ **PHP 7.4 is EOL and support will be discontinued in these libraries soon.** +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 00000000..a79b9f04 --- /dev/null +++ b/devenv.lock @@ -0,0 +1,152 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1675875772, + "narHash": "sha256-sYXHPZ4tsjdG+UXK0mYnABhiS/RuzHiV9uGOU9YakwE=", + "owner": "cachix", + "repo": "devenv", + "rev": "eac5eb12eb42765f5f252972dc876d1f96b03dfe", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1675758091, + "narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1673800717, + "narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1671271357, + "narHash": "sha256-xRJdLbWK4v2SewmSStYrcLa0YGJpleufl44A19XSW8k=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "40f79f003b6377bd2f4ed4027dde1f8f922995dd", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1675688762, + "narHash": "sha256-oit/SxMk0B380ASuztBGQLe8TttO1GJiXF8aZY9AYEc=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "ab608394886fb04b8a5df3cb0bab2598400e3634", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 00000000..8a9cc2e5 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,52 @@ +{ pkgs, ... }: + +{ + + # https://devenv.sh/packages/ + packages = [ pkgs.git ]; + + # https://devenv.sh/languages/ + languages.nix.enable = true; + languages.php.enable = true; + languages.php.package = pkgs.php80; + + # https://devenv.sh/basics/ + env.PROJECT_NAME = "openfeature-php-sdk"; + + # https://devenv.sh/scripts/ + scripts.hello.exec = "echo $ Started devenv shell in $PROJECT_NAME"; + + enterShell = '' + hello + echo + git --version + php --version + echo + + # optimization step -- files and directories that match entries + # in the .gitignore will still be traversed, and the .devenv + # directory contains over 5000 files and 121MB. + if ! grep -E "excludesfile.+\.gitignore" .git/config &>/dev/null + then + git config --local core.excludesfile .gitignore + fi + ''; + + ## https://devenv.sh/pre-commit-hooks/ + pre-commit.hooks = { + # # general formatting + # prettier.enable = true; + # github actions + actionlint.enable = true; + # nix + deadnix.enable = true; + nixfmt.enable = true; + # php + # phpcbf.enable = true; + # # ensure Markdown code is executable + # mdsh.enable = true; + }; + + # https://devenv.sh/processes/ + # processes.ping.exec = "ping example.com"; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 00000000..292df95b --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,5 @@ +inputs: + nixpkgs: + url: github:NixOS/nixpkgs/nixpkgs-unstable + pre-commit-hooks: + url: github:cachix/pre-commit-hooks.nix \ No newline at end of file diff --git a/hooks/DDTrace/README.md b/hooks/DDTrace/README.md index 9a1b8401..6f8fd1fd 100644 --- a/hooks/DDTrace/README.md +++ b/hooks/DDTrace/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/dd-trace-hook/v)](https://packagist.org/packages/open-feature/dd-trace-hook) [![Total Downloads](http://poser.pugx.org/open-feature/dd-trace-hook/downloads)](https://packagist.org/packages/open-feature/dd-trace-hook) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/dd-trace-hook/license)](https://packagist.org/packages/open-feature/dd-trace-hook) ## Overview @@ -47,7 +47,7 @@ For more examples, see the [examples](./examples/). ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/hooks/DDTrace/composer.json b/hooks/DDTrace/composer.json index 57965838..55ebc34f 100644 --- a/hooks/DDTrace/composer.json +++ b/hooks/DDTrace/composer.json @@ -23,8 +23,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.2.0" + "php": "^8", + "open-feature/sdk": "^2.0" }, "require-dev": { "datadog/dd-trace": "^0.82.0", diff --git a/hooks/DDTrace/phpcs.xml.dist b/hooks/DDTrace/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/hooks/DDTrace/phpcs.xml.dist +++ b/hooks/DDTrace/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/hooks/OpenTelemetry/README.md b/hooks/OpenTelemetry/README.md index 29823f57..fb732de4 100644 --- a/hooks/OpenTelemetry/README.md +++ b/hooks/OpenTelemetry/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/otel-hook/v)](https://packagist.org/packages/open-feature/otel-hook) [![Total Downloads](http://poser.pugx.org/open-feature/otel-hook/downloads)](https://packagist.org/packages/open-feature/otel-hook) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/otel-hook/license)](https://packagist.org/packages/open-feature/otel-hook) ## Overview @@ -47,7 +47,7 @@ For more examples, see the [examples](./examples/). ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json index 70a3d219..79dc1567 100644 --- a/hooks/OpenTelemetry/composer.json +++ b/hooks/OpenTelemetry/composer.json @@ -22,8 +22,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.2.0", + "php": "^8", + "open-feature/sdk": "^2.0", "open-telemetry/api": "^0.0.17" }, "require-dev": { diff --git a/hooks/OpenTelemetry/phpcs.xml.dist b/hooks/OpenTelemetry/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/hooks/OpenTelemetry/phpcs.xml.dist +++ b/hooks/OpenTelemetry/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/hooks/OpenTelemetry/src/TracerHelper.php b/hooks/OpenTelemetry/src/TracerHelper.php index 5d08c4b5..795ea2e9 100644 --- a/hooks/OpenTelemetry/src/TracerHelper.php +++ b/hooks/OpenTelemetry/src/TracerHelper.php @@ -13,10 +13,8 @@ class TracerHelper /** * Determines a non-null Tracer to return based on a given input, allowing * multiple types including a PSR-11 container, Tracer, or null - * - * @param ContainerInterface|TracerInterface|null $maybeTracerOrContainer */ - public static function determineTracer($maybeTracerOrContainer = null): TracerInterface + public static function determineTracer(ContainerInterface | TracerInterface | null $maybeTracerOrContainer = null): TracerInterface { if ($maybeTracerOrContainer instanceof TracerInterface) { return $maybeTracerOrContainer; diff --git a/hooks/Validators/README.md b/hooks/Validators/README.md index b62cb85c..135879fd 100644 --- a/hooks/Validators/README.md +++ b/hooks/Validators/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/validators-hook/v)](https://packagist.org/packages/open-feature/validators-hook) [![Total Downloads](http://poser.pugx.org/open-feature/validators-hook/downloads)](https://packagist.org/packages/open-feature/validators-hook) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/validators-hook/license)](https://packagist.org/packages/open-feature/validators-hook) ## Overview @@ -42,7 +42,7 @@ For more examples, see the [examples](./examples/). ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/hooks/Validators/composer.json b/hooks/Validators/composer.json index 6864239f..244a5c5e 100644 --- a/hooks/Validators/composer.json +++ b/hooks/Validators/composer.json @@ -21,8 +21,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.2.0" + "php": "^8", + "open-feature/sdk": "^2.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.25", diff --git a/hooks/Validators/phpcs.xml.dist b/hooks/Validators/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/hooks/Validators/phpcs.xml.dist +++ b/hooks/Validators/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/providers/CloudBees/README.md b/providers/CloudBees/README.md index 6c2dec29..1cc42522 100644 --- a/providers/CloudBees/README.md +++ b/providers/CloudBees/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/cloudbees-provider/v)](https://packagist.org/packages/open-feature/cloudbees-provider) [![Total Downloads](http://poser.pugx.org/open-feature/cloudbees-provider/downloads)](https://packagist.org/packages/open-feature/cloudbees-provider) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/cloudbees-provider/license)](https://packagist.org/packages/open-feature/cloudbees-provider) ## Overview @@ -52,7 +52,7 @@ CloudBeesProvider::shutdown(); ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/providers/CloudBees/composer.json b/providers/CloudBees/composer.json index 2a306099..383564c4 100644 --- a/providers/CloudBees/composer.json +++ b/providers/CloudBees/composer.json @@ -23,8 +23,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.2.0", + "php": "^8", + "open-feature/sdk": "^2.0", "rollout/rox": "^5.0" }, "require-dev": { diff --git a/providers/CloudBees/phpcs.xml.dist b/providers/CloudBees/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/providers/CloudBees/phpcs.xml.dist +++ b/providers/CloudBees/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/providers/CloudBees/src/CloudBeesProvider.php b/providers/CloudBees/src/CloudBeesProvider.php index 392a8c7c..1e65f399 100644 --- a/providers/CloudBees/src/CloudBeesProvider.php +++ b/providers/CloudBees/src/CloudBeesProvider.php @@ -96,7 +96,7 @@ public function resolveFloatValue(string $flagKey, float $defaultValue, ?Evaluat /** * @param mixed[] $defaultValue */ - public function resolveObjectValue(string $flagKey, $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + public function resolveObjectValue(string $flagKey, array $defaultValue, ?EvaluationContext $context = null): ResolutionDetails { return $this->resolve( $defaultValue, @@ -108,22 +108,26 @@ public function resolveObjectValue(string $flagKey, $defaultValue, ?EvaluationCo /** * @param bool|string|int|float|mixed[] $defaultValue */ - private function resolve($defaultValue, callable $fn, ?callable $transformer = null): ResolutionDetails + private function resolve(mixed $defaultValue, callable $fn, ?callable $transformer = null): ResolutionDetails { if (is_null($transformer)) { $transformer = new IdentityTransformer(); } try { - /** @var bool|string|int|float $value */ + /** + * @var bool|string|int|float $value +*/ $value = call_user_func($fn); - /** @var bool|string|int|float|mixed[] $transformed */ + /** + * @var bool|string|int|float|mixed[] $transformed +*/ $transformed = call_user_func($transformer, $value); return (new ResolutionDetailsBuilder()) - ->withValue($transformed) - ->build(); + ->withValue($transformed) + ->build(); } catch (Throwable $err) { $detailsBuilder = new ResolutionDetailsBuilder(); diff --git a/providers/CloudBees/src/transformers/IdentityTransformer.php b/providers/CloudBees/src/transformers/IdentityTransformer.php index 430c305e..071453f4 100644 --- a/providers/CloudBees/src/transformers/IdentityTransformer.php +++ b/providers/CloudBees/src/transformers/IdentityTransformer.php @@ -11,7 +11,7 @@ class IdentityTransformer * * @return bool|string|int|float|mixed[] */ - public function __invoke($x) + public function __invoke(mixed $x): mixed { return $x; } diff --git a/providers/Flagd/README.md b/providers/Flagd/README.md index 992336fa..a7c82272 100644 --- a/providers/Flagd/README.md +++ b/providers/Flagd/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/flagd-provider/v)](https://packagist.org/packages/open-feature/flagd-provider) [![Total Downloads](http://poser.pugx.org/open-feature/flagd-provider/downloads)](https://packagist.org/packages/open-feature/flagd-provider) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/flagd-provider/license)](https://packagist.org/packages/open-feature/flagd-provider) ## Overview @@ -62,7 +62,7 @@ The Flagd server is gRPC but offers gRPC Web endpoints that can be accessed over ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/providers/Flagd/composer.json b/providers/Flagd/composer.json index b9f0ccc6..3972acbf 100644 --- a/providers/Flagd/composer.json +++ b/providers/Flagd/composer.json @@ -21,8 +21,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.1.0", + "php": "^8", + "open-feature/sdk": "^2.0", "php-http/httplug": "^2.3.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", diff --git a/providers/Flagd/phpcs.xml.dist b/providers/Flagd/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/providers/Flagd/phpcs.xml.dist +++ b/providers/Flagd/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/providers/Flagd/src/FlagdProvider.php b/providers/Flagd/src/FlagdProvider.php index 99450b1d..171d25d1 100644 --- a/providers/Flagd/src/FlagdProvider.php +++ b/providers/Flagd/src/FlagdProvider.php @@ -22,10 +22,7 @@ class FlagdProvider extends AbstractProvider implements Provider private ServiceInterface $service; - /** - * @param mixed|IConfig|mixed[] $config - */ - public function __construct($config = null) + public function __construct(mixed $config = null) { $this->config = Validator::validate($config); @@ -52,10 +49,7 @@ public function resolveFloatValue(string $flagKey, float $defaultValue, ?Evaluat return $this->service->resolveValue($flagKey, FlagValueType::FLOAT, $defaultValue, $context); } - /** - * @param mixed[] $defaultValue - */ - public function resolveObjectValue(string $flagKey, $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + public function resolveObjectValue(string $flagKey, mixed $defaultValue, ?EvaluationContext $context = null): ResolutionDetails { return $this->service->resolveValue($flagKey, FlagValueType::OBJECT, $defaultValue, $context); } diff --git a/providers/Flagd/src/config/Validator.php b/providers/Flagd/src/config/Validator.php index 36ecb10c..2302eb66 100644 --- a/providers/Flagd/src/config/Validator.php +++ b/providers/Flagd/src/config/Validator.php @@ -22,10 +22,7 @@ class Validator private const VALID_PORT_RANGE = [1, 65535]; private const VALID_PROTOCOLS = ['grpc', 'http']; - /** - * @param mixed $config - */ - public static function validate($config = null): IConfig + public static function validate(mixed $config = null): IConfig { if ($config instanceof IConfig) { return self::validateConfig($config); @@ -63,10 +60,7 @@ private static function validateConfig(IConfig $config): IConfig return new Config($host, $port, $protocol, $secure, $httpConfig); } - /** - * @param mixed $secure - */ - private static function validateSecure($secure): bool + private static function validateSecure(mixed $secure): bool { if (is_bool($secure)) { return $secure; @@ -75,10 +69,7 @@ private static function validateSecure($secure): bool return Defaults::DEFAULT_SECURE; } - /** - * @param mixed $host - */ - private static function validateHost($host): string + private static function validateHost(mixed $host): string { if (is_string($host) && preg_match(self::VALID_HOST_REGEXP, $host)) { return $host; @@ -87,10 +78,7 @@ private static function validateHost($host): string return Defaults::DEFAULT_HOST; } - /** - * @param mixed $port - */ - private static function validatePort($port): int + private static function validatePort(mixed $port): int { [$minPort, $maxPort] = self::VALID_PORT_RANGE; @@ -101,10 +89,7 @@ private static function validatePort($port): int return Defaults::DEFAULT_PORT; } - /** - * @param mixed $protocol - */ - private static function validateProtocol($protocol): string + private static function validateProtocol(mixed $protocol): string { if (is_string($protocol) && in_array($protocol, self::VALID_PROTOCOLS)) { return $protocol; @@ -113,10 +98,7 @@ private static function validateProtocol($protocol): string return Defaults::DEFAULT_PROTOCOL; } - /** - * @param mixed $httpConfig - */ - private static function validateHttpConfig($httpConfig): ?IHttpConfig + private static function validateHttpConfig(mixed $httpConfig): ?IHttpConfig { if (is_null($httpConfig)) { return null; @@ -131,9 +113,9 @@ private static function validateHttpConfig($httpConfig): ?IHttpConfig $streamFactory = $httpConfig['streamFactory']; if ( - $client instanceof ClientInterface && - $requestFactory instanceof RequestFactoryInterface && - $streamFactory instanceof StreamFactoryInterface + $client instanceof ClientInterface + && $requestFactory instanceof RequestFactoryInterface + && $streamFactory instanceof StreamFactoryInterface ) { return new HttpConfig($client, $requestFactory, $streamFactory); } diff --git a/providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php b/providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php index 55589ffe..c4f6e406 100644 --- a/providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php +++ b/providers/Flagd/src/http/FlagdResponseResolutionDetailsAdapter.php @@ -16,7 +16,7 @@ class FlagdResponseResolutionDetailsAdapter /** * @param mixed[]|bool|DateTime|float|int|string|null $defaultValue */ - public static function forTypeMismatch($defaultValue): ResolutionDetails + public static function forTypeMismatch(mixed $defaultValue): ResolutionDetails { return (new ResolutionDetailsBuilder()) ->withValue($defaultValue) @@ -28,11 +28,13 @@ public static function forTypeMismatch($defaultValue): ResolutionDetails * @param string[] $response * @param mixed[]|bool|DateTime|float|int|string|null $defaultValue */ - public static function forError(array $response, $defaultValue): ResolutionDetails + public static function forError(array $response, mixed $defaultValue): ResolutionDetails { $responseCode = $response['code']; if ($responseCode && ResponseCodeErrorCodeMap::has($responseCode)) { - /** @var ErrorCode $responseErrorCode */ + /** + * @var ErrorCode $responseErrorCode + */ $responseErrorCode = ResponseCodeErrorCodeMap::get($responseCode); $resolutionError = new ResolutionError( diff --git a/providers/Flagd/src/service/ServiceInterface.php b/providers/Flagd/src/service/ServiceInterface.php index fff746c6..c8950c83 100644 --- a/providers/Flagd/src/service/ServiceInterface.php +++ b/providers/Flagd/src/service/ServiceInterface.php @@ -13,5 +13,5 @@ interface ServiceInterface /** * @param mixed[]|bool|DateTime|float|int|string|null $defaultValue */ - public function resolveValue(string $flagKey, string $flagType, $defaultValue, ?EvaluationContext $context): ResolutionDetails; + public function resolveValue(string $flagKey, string $flagType, mixed $defaultValue, ?EvaluationContext $context): ResolutionDetails; } diff --git a/providers/Split/README.md b/providers/Split/README.md index 3f06837c..edd7516b 100644 --- a/providers/Split/README.md +++ b/providers/Split/README.md @@ -3,7 +3,7 @@ [![a](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Latest Stable Version](http://poser.pugx.org/open-feature/split-provider/v)](https://packagist.org/packages/open-feature/split-provider) [![Total Downloads](http://poser.pugx.org/open-feature/split-provider/downloads)](https://packagist.org/packages/open-feature/split-provider) -![PHP 7.4+](https://img.shields.io/badge/php->=7.4-blue.svg) +![PHP 8.0+](https://img.shields.io/badge/php->=8.0-blue.svg) [![License](http://poser.pugx.org/open-feature/split-provider/license)](https://packagist.org/packages/open-feature/split-provider) ## Overview @@ -83,7 +83,7 @@ if ($featureEnabled) { ### PHP Versioning -This library targets PHP version 7.4 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. This package also has a `.tool-versions` file for use with PHP version managers like `asdf`. diff --git a/providers/Split/composer.json b/providers/Split/composer.json index c0083d01..cb09878e 100644 --- a/providers/Split/composer.json +++ b/providers/Split/composer.json @@ -22,8 +22,8 @@ } ], "require": { - "php": "^7.4 || ^8", - "open-feature/sdk": "^1.2.0", + "php": "^8", + "open-feature/sdk": "^2.0", "splitsoftware/split-sdk-php": "^7.1" }, "require-dev": { diff --git a/providers/Split/phpcs.xml.dist b/providers/Split/phpcs.xml.dist index 5ba48465..55d9d3a1 100644 --- a/providers/Split/phpcs.xml.dist +++ b/providers/Split/phpcs.xml.dist @@ -20,9 +20,6 @@ - - - diff --git a/providers/Split/src/SplitProvider.php b/providers/Split/src/SplitProvider.php index 9c93fc25..ae9df27e 100644 --- a/providers/Split/src/SplitProvider.php +++ b/providers/Split/src/SplitProvider.php @@ -33,7 +33,9 @@ class SplitProvider extends AbstractProvider implements Provider { protected const NAME = 'SplitProvider'; - /** The Split factory will only be created one time */ + /** + * The Split factory will only be created one time + */ private static SplitFactoryInterface $factory; private ClientInterface $client; @@ -47,12 +49,11 @@ class SplitProvider extends AbstractProvider implements Provider * * @see https://help.split.io/hc/en-us/articles/360020350372-PHP-SDK#configuration * - * @param string $apiKey The API key for Split * @param mixed[] $options The configuration options for the client * * @throws SplitFactoryCreationException */ - public function __construct(?string $apiKey = '', $options = []) + public function __construct(?string $apiKey = '', array $options = []) { if (isset(self::$factory)) { $factory = self::$factory; @@ -104,7 +105,7 @@ public function resolveFloatValue(string $flagKey, float $defaultValue, ?Evaluat /** * @param mixed[] $defaultValue */ - public function resolveObjectValue(string $flagKey, $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + public function resolveObjectValue(string $flagKey, array $defaultValue, ?EvaluationContext $context = null): ResolutionDetails { return $this->resolveValue($flagKey, FlagValueType::OBJECT, $defaultValue, $context); } @@ -112,7 +113,7 @@ public function resolveObjectValue(string $flagKey, $defaultValue, ?EvaluationCo /** * @param bool|string|int|float|mixed[] $defaultValue */ - private function resolveValue(string $flagKey, string $flagType, $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + private function resolveValue(string $flagKey, string $flagType, mixed $defaultValue, ?EvaluationContext $context = null): ResolutionDetails { try { if (is_null($context)) { From 26c62609de6f01a8d60106b065535a06f1e959fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 23:49:46 -0500 Subject: [PATCH 49/90] chore(main): release open-feature/split-provider 0.3.0 (#60) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 14 +++++++------- providers/Split/CHANGELOG.md | 7 +++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 544118f2..3bbbd594 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,8 +1,8 @@ -{ - "hooks/DDTrace":"0.2.0", - "hooks/OpenTelemetry":"0.2.0", - "hooks/Validators":"0.2.0", - "providers/CloudBees":"0.3.0", - "providers/Flagd":"0.4.0", - "providers/Split":"0.3.0" +{ + "hooks/DDTrace": "0.2.0", + "hooks/OpenTelemetry": "0.2.0", + "hooks/Validators": "0.2.0", + "providers/CloudBees": "0.3.0", + "providers/Flagd": "0.4.0", + "providers/Split": "0.3.0" } \ No newline at end of file diff --git a/providers/Split/CHANGELOG.md b/providers/Split/CHANGELOG.md index a0f8406f..e15d6d64 100644 --- a/providers/Split/CHANGELOG.md +++ b/providers/Split/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.3.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/split-provider-0.3.0...open-feature/split-provider-0.3.0) (2023-02-12) + + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + ## 0.3.0 (2023-01-09) From b50a40fa51c29be151d6c1a661dcc1875a5204b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 23:50:12 -0500 Subject: [PATCH 50/90] chore(main): release open-feature/dd-trace-hook 0.2.0 (#65) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/DDTrace/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hooks/DDTrace/CHANGELOG.md b/hooks/DDTrace/CHANGELOG.md index ccb9bb45..2f0349c2 100644 --- a/hooks/DDTrace/CHANGELOG.md +++ b/hooks/DDTrace/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/dd-trace-hook-0.2.0...open-feature/dd-trace-hook-0.2.0) (2023-02-12) + + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + ## 0.2.0 (2023-01-09) From 1a255ccc37bbfe1852c71424c133ea58527970d8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 23:50:18 -0500 Subject: [PATCH 51/90] chore(main): release open-feature/validators-hook 0.2.0 (#62) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/Validators/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hooks/Validators/CHANGELOG.md b/hooks/Validators/CHANGELOG.md index fe7bc168..2ccfd5e7 100644 --- a/hooks/Validators/CHANGELOG.md +++ b/hooks/Validators/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/validators-hook-0.2.0...open-feature/validators-hook-0.2.0) (2023-02-12) + + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + ## 0.2.0 (2023-01-09) From 0cfc58d4e350d5549c845fe155e34db153190518 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Feb 2023 23:50:27 -0500 Subject: [PATCH 52/90] chore(main): release open-feature/flagd-provider 0.4.0 (#61) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- providers/Flagd/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/providers/Flagd/CHANGELOG.md b/providers/Flagd/CHANGELOG.md index c80783a6..c6f2bd0a 100644 --- a/providers/Flagd/CHANGELOG.md +++ b/providers/Flagd/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.4.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/flagd-provider-0.4.0...open-feature/flagd-provider-0.4.0) (2023-02-12) + + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + ## 0.4.0 (2023-01-09) From 981aed3aaaf436bdb8b3e2ddf8faa56112138c94 Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Fri, 14 Apr 2023 16:52:36 -0400 Subject: [PATCH 53/90] update link to use new doc domain --- .../Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveFloatRequest.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveFloatResponse.php | 8 ++++---- providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveIntResponse.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveObjectRequest.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveObjectResponse.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveStringRequest.php | 8 ++++---- .../Flagd/proto/php/Schema/V1/ResolveStringResponse.php | 8 ++++---- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php index 70bea8da..9ed905e8 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanRequest.php @@ -22,7 +22,7 @@ class ResolveBooleanRequest extends \Google\Protobuf\Internal\Message */ protected $flag_key = ''; /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; */ @@ -37,7 +37,7 @@ class ResolveBooleanRequest extends \Google\Protobuf\Internal\Message * @type string $flag_key * Flag key of the requested flag. * @type \Google\Protobuf\Struct $context - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * } */ public function __construct($data = NULL) { @@ -72,7 +72,7 @@ public function setFlagKey($var) } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @return \Google\Protobuf\Struct|null @@ -93,7 +93,7 @@ public function clearContext() } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @param \Google\Protobuf\Struct $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php index acee0ed2..a2edf802 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveBooleanResponse.php @@ -22,7 +22,7 @@ class ResolveBooleanResponse extends \Google\Protobuf\Internal\Message */ protected $value = false; /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; */ @@ -43,7 +43,7 @@ class ResolveBooleanResponse extends \Google\Protobuf\Internal\Message * @type bool $value * The response value of the boolean flag evaluation, will be unset in the case of error. * @type string $reason - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * @type string $variant * The variant name of the returned flag value. * } @@ -80,7 +80,7 @@ public function setValue($var) } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @return string @@ -91,7 +91,7 @@ public function getReason() } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @param string $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php index 87194e02..6555908e 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveFloatRequest.php @@ -22,7 +22,7 @@ class ResolveFloatRequest extends \Google\Protobuf\Internal\Message */ protected $flag_key = ''; /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; */ @@ -37,7 +37,7 @@ class ResolveFloatRequest extends \Google\Protobuf\Internal\Message * @type string $flag_key * Flag key of the requested flag. * @type \Google\Protobuf\Struct $context - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * } */ public function __construct($data = NULL) { @@ -72,7 +72,7 @@ public function setFlagKey($var) } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @return \Google\Protobuf\Struct|null @@ -93,7 +93,7 @@ public function clearContext() } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @param \Google\Protobuf\Struct $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php index 1b96a349..3cc01526 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveFloatResponse.php @@ -22,7 +22,7 @@ class ResolveFloatResponse extends \Google\Protobuf\Internal\Message */ protected $value = 0.0; /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; */ @@ -43,7 +43,7 @@ class ResolveFloatResponse extends \Google\Protobuf\Internal\Message * @type float $value * The response value of the float flag evaluation, will be empty in the case of error. * @type string $reason - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * @type string $variant * The variant name of the returned flag value. * } @@ -80,7 +80,7 @@ public function setValue($var) } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @return string @@ -91,7 +91,7 @@ public function getReason() } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @param string $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php index 71b11647..ce8d2b9b 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveIntRequest.php @@ -22,7 +22,7 @@ class ResolveIntRequest extends \Google\Protobuf\Internal\Message */ protected $flag_key = ''; /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; */ @@ -37,7 +37,7 @@ class ResolveIntRequest extends \Google\Protobuf\Internal\Message * @type string $flag_key * Flag key of the requested flag. * @type \Google\Protobuf\Struct $context - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * } */ public function __construct($data = NULL) { @@ -72,7 +72,7 @@ public function setFlagKey($var) } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @return \Google\Protobuf\Struct|null @@ -93,7 +93,7 @@ public function clearContext() } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @param \Google\Protobuf\Struct $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php index 556b6c35..5e774eff 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveIntResponse.php @@ -22,7 +22,7 @@ class ResolveIntResponse extends \Google\Protobuf\Internal\Message */ protected $value = 0; /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; */ @@ -43,7 +43,7 @@ class ResolveIntResponse extends \Google\Protobuf\Internal\Message * @type int|string $value * The response value of the int flag evaluation, will be unset in the case of error. * @type string $reason - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * @type string $variant * The variant name of the returned flag value. * } @@ -80,7 +80,7 @@ public function setValue($var) } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @return string @@ -91,7 +91,7 @@ public function getReason() } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @param string $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php index d2428b20..8b858214 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveObjectRequest.php @@ -22,7 +22,7 @@ class ResolveObjectRequest extends \Google\Protobuf\Internal\Message */ protected $flag_key = ''; /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; */ @@ -37,7 +37,7 @@ class ResolveObjectRequest extends \Google\Protobuf\Internal\Message * @type string $flag_key * Flag key of the requested flag. * @type \Google\Protobuf\Struct $context - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * } */ public function __construct($data = NULL) { @@ -72,7 +72,7 @@ public function setFlagKey($var) } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @return \Google\Protobuf\Struct|null @@ -93,7 +93,7 @@ public function clearContext() } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @param \Google\Protobuf\Struct $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php index 6f38a5c9..04804eb4 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveObjectResponse.php @@ -23,7 +23,7 @@ class ResolveObjectResponse extends \Google\Protobuf\Internal\Message */ protected $value = null; /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; */ @@ -45,7 +45,7 @@ class ResolveObjectResponse extends \Google\Protobuf\Internal\Message * The response value of the object flag evaluation, will be unset in the case of error. * NOTE: This structure will need to be decoded from google/protobuf/struct.proto before it is returned to the SDK * @type string $reason - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * @type string $variant * The variant name of the returned flag value. * } @@ -94,7 +94,7 @@ public function setValue($var) } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @return string @@ -105,7 +105,7 @@ public function getReason() } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @param string $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php b/providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php index 7cde269d..d3c394b1 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveStringRequest.php @@ -22,7 +22,7 @@ class ResolveStringRequest extends \Google\Protobuf\Internal\Message */ protected $flag_key = ''; /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; */ @@ -37,7 +37,7 @@ class ResolveStringRequest extends \Google\Protobuf\Internal\Message * @type string $flag_key * Flag key of the requested flag. * @type \Google\Protobuf\Struct $context - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * } */ public function __construct($data = NULL) { @@ -72,7 +72,7 @@ public function setFlagKey($var) } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @return \Google\Protobuf\Struct|null @@ -93,7 +93,7 @@ public function clearContext() } /** - * Object structure describing the EvaluationContext used in the flag evaluation, see https://docs.openfeature.dev/docs/reference/concepts/evaluation-context + * Object structure describing the EvaluationContext used in the flag evaluation, see https://openfeature.dev/docs/reference/concepts/evaluation-context * * Generated from protobuf field .google.protobuf.Struct context = 2 [json_name = "context"]; * @param \Google\Protobuf\Struct $var diff --git a/providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php b/providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php index bd256357..b72a5ce9 100644 --- a/providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php +++ b/providers/Flagd/proto/php/Schema/V1/ResolveStringResponse.php @@ -22,7 +22,7 @@ class ResolveStringResponse extends \Google\Protobuf\Internal\Message */ protected $value = ''; /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; */ @@ -43,7 +43,7 @@ class ResolveStringResponse extends \Google\Protobuf\Internal\Message * @type string $value * The response value of the string flag evaluation, will be unset in the case of error. * @type string $reason - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * @type string $variant * The variant name of the returned flag value. * } @@ -80,7 +80,7 @@ public function setValue($var) } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @return string @@ -91,7 +91,7 @@ public function getReason() } /** - * The reason for the given return value, see https://docs.openfeature.dev/docs/specification/types#resolution-details + * The reason for the given return value, see https://openfeature.dev/docs/specification/types#resolution-details * * Generated from protobuf field string reason = 2 [json_name = "reason"]; * @param string $var From 359558205ded2bec9938502f699694716fb00e72 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 22:25:19 -0400 Subject: [PATCH 54/90] chore(deps): update dependency phpstan/phpstan to ~1.10.0 (#70) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hooks/DDTrace/composer.json | 2 +- hooks/OpenTelemetry/composer.json | 2 +- hooks/Validators/composer.json | 2 +- providers/CloudBees/composer.json | 2 +- providers/Flagd/composer.json | 2 +- providers/Split/composer.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hooks/DDTrace/composer.json b/hooks/DDTrace/composer.json index 55ebc34f..a385e0e2 100644 --- a/hooks/DDTrace/composer.json +++ b/hooks/DDTrace/composer.json @@ -38,7 +38,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.9.1", diff --git a/hooks/OpenTelemetry/composer.json b/hooks/OpenTelemetry/composer.json index 79dc1567..ba4b9e8a 100644 --- a/hooks/OpenTelemetry/composer.json +++ b/hooks/OpenTelemetry/composer.json @@ -37,7 +37,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.9.1", diff --git a/hooks/Validators/composer.json b/hooks/Validators/composer.json index 244a5c5e..9ac24a05 100644 --- a/hooks/Validators/composer.json +++ b/hooks/Validators/composer.json @@ -35,7 +35,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.9.1", diff --git a/providers/CloudBees/composer.json b/providers/CloudBees/composer.json index 383564c4..67640d8a 100644 --- a/providers/CloudBees/composer.json +++ b/providers/CloudBees/composer.json @@ -37,7 +37,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.11.0", diff --git a/providers/Flagd/composer.json b/providers/Flagd/composer.json index 3972acbf..fcbac084 100644 --- a/providers/Flagd/composer.json +++ b/providers/Flagd/composer.json @@ -39,7 +39,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.11.0", diff --git a/providers/Split/composer.json b/providers/Split/composer.json index cb09878e..cdebe159 100644 --- a/providers/Split/composer.json +++ b/providers/Split/composer.json @@ -37,7 +37,7 @@ "php-parallel-lint/php-console-highlighter": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "~1.9.0", + "phpstan/phpstan": "~1.10.0", "phpstan/phpstan-mockery": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "psalm/plugin-mockery": "^0.11.0", From 4689ff0e212291871c3b54eeefd8c3d5bdf93c09 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:00:20 -0400 Subject: [PATCH 55/90] ci: initial draft of gitsplit replacement (#73) * ci: initial draft of gitsplit replacement Fixes: #55 Signed-off-by: Tom Carrio * refactor: target specific release tag name and break out jobs for each split Signed-off-by: Tom Carrio --------- Signed-off-by: Tom Carrio --- .github/workflows/split_monorepo.yaml | 134 ++++++++++++++++-- .../.github/workflows/release-please.yml | 18 --- .../.github/workflows/release-please.yml | 18 --- .../.github/workflows/release-please.yml | 18 --- .../.github/workflows/release-please.yml | 18 --- .../.github/workflows/release-please.yml | 18 --- .../.github/workflows/release-please.yml | 18 --- 7 files changed, 121 insertions(+), 121 deletions(-) delete mode 100644 hooks/DDTrace/.github/workflows/release-please.yml delete mode 100644 hooks/OpenTelemetry/.github/workflows/release-please.yml delete mode 100644 hooks/Validators/.github/workflows/release-please.yml delete mode 100644 providers/CloudBees/.github/workflows/release-please.yml delete mode 100644 providers/Flagd/.github/workflows/release-please.yml delete mode 100644 providers/Split/.github/workflows/release-please.yml diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index 2a1faefa..63953a25 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -1,23 +1,131 @@ name: gitsplit on: - push: - branches: - - main - - split release: types: [published] - create: - workflow_dispatch: jobs: - gitsplit: + split-hook-dd-trace: runs-on: ubuntu-latest steps: - name: checkout - run: git clone "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout $GITHUB_SHA - - name: Split repositories - uses: docker://jderusse/gitsplit:latest + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter with: - args: gitsplit - env: - GH_TOKEN: ${{ secrets.GITSPLIT_TOKEN }} \ No newline at end of file + filters: | + src: + - 'hooks/DDTrace/**' + - name: push-hook-dd-trace + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: dd-trace-hook + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter hooks/DDTrace/' + + split-hook-otel: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + src: + - 'hooks/OpenTelemetry/**' + - name: push-hook-otel + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: otel-hook + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter hooks/OpenTelemetry/' + + split-hook-validator: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + src: + - 'hooks/Validators/**' + - name: push-hook-validator + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: validators-hook + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter hooks/Validators/' + + split-provider-cloudbees: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + src: + - 'providers/CloudBees/**' + - name: push-provider-cloudbees + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: cloudbees-provider + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter providers/CloudBees/' + + split-provider-flagd: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + src: + - 'providers/Flagd/**' + - name: push-provider-flagd + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: flagd-provider + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter providers/Flagd/' + + split-provider-split: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + src: + - 'providers/Split/**' + - name: push-provider-split + uses: wmde/git-filter-repo-docker-action@v1 + if: steps.filter.outputs.workflows == 'true' + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: split-provider + targetBranch: ${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter providers/Split/' diff --git a/hooks/DDTrace/.github/workflows/release-please.yml b/hooks/DDTrace/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/hooks/DDTrace/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main diff --git a/hooks/OpenTelemetry/.github/workflows/release-please.yml b/hooks/OpenTelemetry/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/hooks/OpenTelemetry/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main diff --git a/hooks/Validators/.github/workflows/release-please.yml b/hooks/Validators/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/hooks/Validators/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main diff --git a/providers/CloudBees/.github/workflows/release-please.yml b/providers/CloudBees/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/providers/CloudBees/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main diff --git a/providers/Flagd/.github/workflows/release-please.yml b/providers/Flagd/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/providers/Flagd/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main diff --git a/providers/Split/.github/workflows/release-please.yml b/providers/Split/.github/workflows/release-please.yml deleted file mode 100644 index 93659057..00000000 --- a/providers/Split/.github/workflows/release-please.yml +++ /dev/null @@ -1,18 +0,0 @@ -on: - push: - branches: - - main - -name: Run Release Please -jobs: - release-please: - runs-on: ubuntu-latest - - # Release-please creates a PR that tracks all changes - steps: - - uses: google-github-actions/release-please-action@v3 - id: release - with: - command: manifest - token: ${{secrets.GITHUB_TOKEN}} - default-branch: main From 66789207c3dc169d75ef0351ac297b07d9b9bb51 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:05:40 -0400 Subject: [PATCH 56/90] ci: remove paths filter due to limitations of release changesets --- .github/workflows/split_monorepo.yaml | 44 +-------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index 63953a25..a6ca5417 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -1,4 +1,4 @@ -name: gitsplit +name: split-monorepo on: release: types: [published] @@ -9,15 +9,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'hooks/DDTrace/**' - name: push-hook-dd-trace uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php @@ -30,15 +23,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'hooks/OpenTelemetry/**' - name: push-hook-otel uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php @@ -51,15 +37,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'hooks/Validators/**' - name: push-hook-validator uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php @@ -72,15 +51,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'providers/CloudBees/**' - name: push-provider-cloudbees uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php @@ -93,15 +65,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'providers/Flagd/**' - name: push-provider-flagd uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php @@ -114,15 +79,8 @@ jobs: steps: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - src: - - 'providers/Split/**' - name: push-provider-split uses: wmde/git-filter-repo-docker-action@v1 - if: steps.filter.outputs.workflows == 'true' with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php From ec7dfd1e289c96502419334f2c4311c2d9746db0 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:10:21 -0400 Subject: [PATCH 57/90] ci: use GITSPLIT_TOKEN secret for SSH key --- .github/workflows/split_monorepo.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index a6ca5417..d703a6f7 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -12,7 +12,7 @@ jobs: - name: push-hook-dd-trace uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: dd-trace-hook targetBranch: ${{ github.event.release.tag_name }} @@ -26,7 +26,7 @@ jobs: - name: push-hook-otel uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: otel-hook targetBranch: ${{ github.event.release.tag_name }} @@ -40,7 +40,7 @@ jobs: - name: push-hook-validator uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: validators-hook targetBranch: ${{ github.event.release.tag_name }} @@ -54,7 +54,7 @@ jobs: - name: push-provider-cloudbees uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: cloudbees-provider targetBranch: ${{ github.event.release.tag_name }} @@ -68,7 +68,7 @@ jobs: - name: push-provider-flagd uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: flagd-provider targetBranch: ${{ github.event.release.tag_name }} @@ -82,7 +82,7 @@ jobs: - name: push-provider-split uses: wmde/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + privateKey: ${{ secrets.GITSPLIT_TOKEN }} targetOrg: open-feature-php targetRepo: split-provider targetBranch: ${{ github.event.release.tag_name }} From 99ba83c262e26ecf426abc1331f5c148df5af2e2 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:20:16 -0400 Subject: [PATCH 58/90] ci: revert to SSH_PRIVATE_KEY and use custom runner for git-filter-repo --- .github/workflows/split_monorepo.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index d703a6f7..709da95c 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -10,9 +10,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-hook-dd-trace - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: dd-trace-hook targetBranch: ${{ github.event.release.tag_name }} @@ -24,9 +24,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-hook-otel - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: otel-hook targetBranch: ${{ github.event.release.tag_name }} @@ -38,9 +38,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-hook-validator - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: validators-hook targetBranch: ${{ github.event.release.tag_name }} @@ -52,9 +52,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-provider-cloudbees - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: cloudbees-provider targetBranch: ${{ github.event.release.tag_name }} @@ -66,9 +66,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-provider-flagd - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: flagd-provider targetBranch: ${{ github.event.release.tag_name }} @@ -80,9 +80,9 @@ jobs: - name: checkout run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - name: push-provider-split - uses: wmde/git-filter-repo-docker-action@v1 + uses: tcarrio/git-filter-repo-docker-action@v1 with: - privateKey: ${{ secrets.GITSPLIT_TOKEN }} + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: split-provider targetBranch: ${{ github.event.release.tag_name }} From d4c8a85fa42700671e48250f5f15133c0668387a Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:26:07 -0400 Subject: [PATCH 59/90] ci: add force flag for git-filter-repo command --- .github/workflows/split_monorepo.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index 709da95c..cccb0693 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -16,7 +16,7 @@ jobs: targetOrg: open-feature-php targetRepo: dd-trace-hook targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/DDTrace/' + filterArguments: '--subdirectory-filter hooks/DDTrace/ --force' split-hook-otel: runs-on: ubuntu-latest @@ -30,7 +30,7 @@ jobs: targetOrg: open-feature-php targetRepo: otel-hook targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/OpenTelemetry/' + filterArguments: '--subdirectory-filter hooks/OpenTelemetry/ --force' split-hook-validator: runs-on: ubuntu-latest @@ -44,7 +44,7 @@ jobs: targetOrg: open-feature-php targetRepo: validators-hook targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/Validators/' + filterArguments: '--subdirectory-filter hooks/Validators/ --force' split-provider-cloudbees: runs-on: ubuntu-latest @@ -58,7 +58,7 @@ jobs: targetOrg: open-feature-php targetRepo: cloudbees-provider targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/CloudBees/' + filterArguments: '--subdirectory-filter providers/CloudBees/ --force' split-provider-flagd: runs-on: ubuntu-latest @@ -72,7 +72,7 @@ jobs: targetOrg: open-feature-php targetRepo: flagd-provider targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/Flagd/' + filterArguments: '--subdirectory-filter providers/Flagd/ --force' split-provider-split: runs-on: ubuntu-latest @@ -86,4 +86,4 @@ jobs: targetOrg: open-feature-php targetRepo: split-provider targetBranch: ${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/Split/' + filterArguments: '--subdirectory-filter providers/Split/ --force' From 5872cf540e782a05b94196b0b0a814104452bd77 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 3 May 2023 23:28:32 -0400 Subject: [PATCH 60/90] ci: prepend targetBranch with refs/tags --- .github/workflows/split_monorepo.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index cccb0693..eac7db84 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -15,7 +15,7 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: dd-trace-hook - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter hooks/DDTrace/ --force' split-hook-otel: @@ -29,7 +29,7 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: otel-hook - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter hooks/OpenTelemetry/ --force' split-hook-validator: @@ -43,7 +43,7 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: validators-hook - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter hooks/Validators/ --force' split-provider-cloudbees: @@ -57,7 +57,7 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: cloudbees-provider - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter providers/CloudBees/ --force' split-provider-flagd: @@ -71,7 +71,7 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: flagd-provider - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter providers/Flagd/ --force' split-provider-split: @@ -85,5 +85,5 @@ jobs: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php targetRepo: split-provider - targetBranch: ${{ github.event.release.tag_name }} + targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter providers/Split/ --force' From bf6f449ea790c0021698d33ebb59fab576e23341 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Tue, 16 May 2023 17:44:12 -0400 Subject: [PATCH 61/90] feat(flagd): support newer psr/log Signed-off-by: Tom Carrio --- providers/Flagd/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/Flagd/composer.json b/providers/Flagd/composer.json index fcbac084..58686682 100644 --- a/providers/Flagd/composer.json +++ b/providers/Flagd/composer.json @@ -27,7 +27,7 @@ "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0", - "psr/log": "^1.1" + "psr/log": "^2.0 || ^3.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.25", From bb18c04af7280c71c013d5a2e11903506b815f8b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 20 May 2023 09:35:58 -0400 Subject: [PATCH 62/90] fix(deps): update dependency psr/http-message to v2 (#72) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- providers/Flagd/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/Flagd/composer.json b/providers/Flagd/composer.json index 58686682..59b95c82 100644 --- a/providers/Flagd/composer.json +++ b/providers/Flagd/composer.json @@ -26,7 +26,7 @@ "php-http/httplug": "^2.3.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^2.0", "psr/log": "^2.0 || ^3.0" }, "require-dev": { From 3727b134e950df16d7707be27a7e6902ea9a65c4 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sat, 20 May 2023 09:54:17 -0400 Subject: [PATCH 63/90] ci: various fixes for linting (#81) * style: import dd-trace hook before use in _autoload.php Signed-off-by: Tom Carrio * style: import before use in otel _autoload.php Signed-off-by: Tom Carrio * refactor: support logger in SplitProvider Signed-off-by: Tom Carrio * test: return using stringable magic method FlagdProviderTest.php Signed-off-by: Tom Carrio --------- Signed-off-by: Tom Carrio --- hooks/DDTrace/src/_autoload.php | 4 +++- hooks/OpenTelemetry/src/_autoload.php | 4 +++- providers/Flagd/tests/unit/FlagdProviderTest.php | 4 ++-- providers/Split/src/SplitProvider.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/hooks/DDTrace/src/_autoload.php b/hooks/DDTrace/src/_autoload.php index 64da5504..8d397662 100644 --- a/hooks/DDTrace/src/_autoload.php +++ b/hooks/DDTrace/src/_autoload.php @@ -2,5 +2,7 @@ declare(strict_types=1); +use OpenFeature\Hooks\DDTrace\DDTraceHook; + // automatically registers the DDTraceHook for OpenFeature -OpenFeature\Hooks\DDTrace\DDTraceHook::register(); +DDTraceHook::register(); diff --git a/hooks/OpenTelemetry/src/_autoload.php b/hooks/OpenTelemetry/src/_autoload.php index 69fb8174..ac8b3881 100644 --- a/hooks/OpenTelemetry/src/_autoload.php +++ b/hooks/OpenTelemetry/src/_autoload.php @@ -2,5 +2,7 @@ declare(strict_types=1); +use OpenFeature\Hooks\OpenTelemetry\OpenTelemetryHook; + // automatically registers the OTel hook for OpenFeature -OpenFeature\Hooks\OpenTelemetry\OpenTelemetryHook::register(); +OpenTelemetryHook::register(); diff --git a/providers/Flagd/tests/unit/FlagdProviderTest.php b/providers/Flagd/tests/unit/FlagdProviderTest.php index 25b70c87..8777e11b 100644 --- a/providers/Flagd/tests/unit/FlagdProviderTest.php +++ b/providers/Flagd/tests/unit/FlagdProviderTest.php @@ -57,7 +57,7 @@ public function testCanInstantiateHttpWithConfigObject(): void $mockStreamFactory->shouldReceive('createStream')->andReturn($mockStream); $mockResponse = $this->mockery(ResponseInterface::class); - $mockResponse->shouldReceive('getBody')->andReturn("{ + $mockResponse->shouldReceive('getBody->__toString')->andReturn("{ \"value\":\"{$expectedValue}\", \"variant\":\"{$expectedVariant}\", \"reason\":\"{$expectedReason}\" @@ -111,7 +111,7 @@ public function testCanInstantiateHttpWithConfigArray(): void $mockStreamFactory->shouldReceive('createStream')->andReturn($mockStream); $mockResponse = $this->mockery(ResponseInterface::class); - $mockResponse->shouldReceive('getBody')->andReturn("{ + $mockResponse->shouldReceive('getBody->__toString')->andReturn("{ \"value\":\"{$expectedValue}\", \"variant\":\"{$expectedVariant}\", \"reason\":\"{$expectedReason}\" diff --git a/providers/Split/src/SplitProvider.php b/providers/Split/src/SplitProvider.php index ae9df27e..9a4dc465 100644 --- a/providers/Split/src/SplitProvider.php +++ b/providers/Split/src/SplitProvider.php @@ -70,7 +70,7 @@ public function __construct(?string $apiKey = '', array $options = []) $this->client = $factory->client(); } - public function setLogger(LoggerInterface $logger) + public function setLogger(LoggerInterface $logger): void { Di::setLogger($logger); } From 684367cd14b6b55cded5accdc5b92eb00986404c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9opold=20Jacquot?= Date: Fri, 21 Jul 2023 14:42:32 +0200 Subject: [PATCH 64/90] fix: flagd documentation (#83) Signed-off-by: Leopold Jacquot --- providers/Flagd/README.md | 4 +-- providers/Flagd/examples/Grpc/README.md | 5 --- providers/Flagd/examples/Grpc/composer.json | 21 ----------- providers/Flagd/examples/Grpc/src/main.php | 39 --------------------- providers/Flagd/examples/Http/README.md | 11 +----- 5 files changed, 3 insertions(+), 77 deletions(-) delete mode 100644 providers/Flagd/examples/Grpc/README.md delete mode 100644 providers/Flagd/examples/Grpc/composer.json delete mode 100644 providers/Flagd/examples/Grpc/src/main.php diff --git a/providers/Flagd/README.md b/providers/Flagd/README.md index a7c82272..d5d09f75 100644 --- a/providers/Flagd/README.md +++ b/providers/Flagd/README.md @@ -37,7 +37,7 @@ OpenFeatureAPI::setProvider(new FlagdProvider([ 'host' => 'localhost', 'port' => 8013, 'secure' => true, - 'http' => [ + 'httpConfig' => [ 'client' => $client, 'requestFactory' => $requestFactory, 'streamFactory' => $streamFactory, @@ -49,7 +49,7 @@ OpenFeatureAPI::setProvider(new FlagdProvider([ - **host**: string _(defaults to "localhost")_ - **port**: number _(defaults to 8013)_ - **secure**: true | false _(defaults to false)_ -- **http**: An array or `HttpConfig` object, providing implementations for PSR interfaces +- **httpConfig**: An array or `HttpConfig` object, providing implementations for PSR interfaces - **client**: a `ClientInterface` implementation - **requestFactory**: a `RequestFactoryInterface` implementation - **streamFactory**: a `StreamFactoryInterface` implementation diff --git a/providers/Flagd/examples/Grpc/README.md b/providers/Flagd/examples/Grpc/README.md deleted file mode 100644 index 14077cf0..00000000 --- a/providers/Flagd/examples/Grpc/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# OpenFeature flagd gRPC example - -This example provides a simple case of working with the OpenFeature API, creating a client, setting a provider, and resolving a value. - -It uses the `Flagd` provider and communicates over gRPC. \ No newline at end of file diff --git a/providers/Flagd/examples/Grpc/composer.json b/providers/Flagd/examples/Grpc/composer.json deleted file mode 100644 index 15466ff5..00000000 --- a/providers/Flagd/examples/Grpc/composer.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "open-feature/flagd-grpc-example", - "description": "An example of using OpenFeature with the Flagd provider over gRPC", - "type": "project", - "license": "Apache-2.0", - "autoload": { - "psr-4": { - "OpenFeature\\Providers\\Examples\\FlagdGrpcExample\\": "src/" - } - }, - "authors": [ - { - "name": "Tom Carrio", - "email": "tom@carrio.dev" - } - ], - "require": { - "open-feature/sdk": "^1.2.0", - "monolog/monolog": "^2.8" - } -} diff --git a/providers/Flagd/examples/Grpc/src/main.php b/providers/Flagd/examples/Grpc/src/main.php deleted file mode 100644 index ab1118e5..00000000 --- a/providers/Flagd/examples/Grpc/src/main.php +++ /dev/null @@ -1,39 +0,0 @@ -pushHandler(new StreamHandler('logs/openfeature.log', Logger::WARNING)); - -$api->setLogger($logger); - -// Configure a flagd provider -$provider = new FlagdProvider([ - 'host' => 'localhost', - 'port' => 8013, - 'secure' => false, - 'protocol' => 'grpc' -]); - -$api->setProvider($provider); - -// Retrieve an OpenFeatureClient -$client = $api->getClient('grpc-example', '1.0'); - -// Resolve a value -$flagValue = $client->getBooleanDetails('dev.openfeature.example_flag', true, null, null); - -$logger->info("Resolved the boolean value: " . ($flagValue ? 'true' : 'false')); \ No newline at end of file diff --git a/providers/Flagd/examples/Http/README.md b/providers/Flagd/examples/Http/README.md index a343e223..de296d72 100644 --- a/providers/Flagd/examples/Http/README.md +++ b/providers/Flagd/examples/Http/README.md @@ -1,10 +1 @@ -# OpenFeature flagd HTTP example - - -> ⚠️ Warning -> -> This example is based on currently unimplemented code. -> It may also never be provided, such that only gRPC is -> available, pending design decisions on the underlying -> `flagd` service - +# OpenFeature flagd HTTP example \ No newline at end of file From 9041190fa7bcfff9a3befd2f737906e207026717 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Fri, 21 Jul 2023 08:49:29 -0400 Subject: [PATCH 65/90] ci: disable fail-fast behavior (#90) there are scenarios where some providers may fail and it may be entirely on downstream dependencies or configurations unrelated to a PR. this change allows a full PR's CI jobs to execute regardless of a failure in another job. Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 33cf9c7f..2f555bfc 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -20,6 +20,7 @@ jobs: - providers/Flagd - providers/Split - providers/CloudBees + fail-fast: false # todo exclude some matrix combinations based on php version requirements # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#excluding-matrix-configurations From 044ccd5a0cbda4d2ab046b36d729e3badf6ead2a Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Fri, 21 Jul 2023 09:34:25 -0400 Subject: [PATCH 66/90] ci: disable CloudBees CI (#92) revert after issue is resolved Signed-off-by: Tom Carrio --- .github/workflows/php-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 2f555bfc..28eb2f9d 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -19,7 +19,7 @@ jobs: - hooks/Validators - providers/Flagd - providers/Split - - providers/CloudBees + # - providers/CloudBees fail-fast: false # todo exclude some matrix combinations based on php version requirements From 13ebc3c5f82c57a57dec92ed477d5ea6045677d3 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Wed, 1 Nov 2023 17:40:44 -0400 Subject: [PATCH 67/90] docs: update README.md to include integrations terminology Signed-off-by: Tom Carrio --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0946782f..42afa3a0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Overview -The `php-contrib-sdk` repository is a monorepository containing various providers and hooks for OpenFeature's PHP SDK. Packages include: +The `php-contrib-sdk` repository is a monorepository containing various providers, hooks, and other integrations for OpenFeature's PHP SDK. Packages include: - Providers - [Flagd](./providers/Flagd/README.md) From 0fe51732e326a6b4d34346f09a12b1929a416e1f Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 17 Jan 2024 13:55:25 -0500 Subject: [PATCH 68/90] chore: add CODEOWNERS (#102) Signed-off-by: Todd Baert --- CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..ad0f3c91 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,6 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence +# +# Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-php/workgroup.yaml +# +* @open-feature/sdk-php-maintainers From 42919fdb8a2d3992ac529ddd7e90d6b99b340732 Mon Sep 17 00:00:00 2001 From: Alexandr Date: Mon, 5 Aug 2024 20:56:54 +0200 Subject: [PATCH 69/90] fix: declaration for provider name (#105) Signed-off-by: Alex Podgorbunschih --- providers/CloudBees/src/CloudBeesProvider.php | 2 +- providers/CloudBees/tests/integration/CloudBeesProviderTest.php | 1 + providers/Flagd/src/FlagdProvider.php | 2 +- providers/Flagd/tests/unit/FlagdProviderTest.php | 1 + providers/Split/src/SplitProvider.php | 2 +- providers/Split/tests/unit/SplitProviderTest.php | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/providers/CloudBees/src/CloudBeesProvider.php b/providers/CloudBees/src/CloudBeesProvider.php index 1e65f399..62f42226 100644 --- a/providers/CloudBees/src/CloudBeesProvider.php +++ b/providers/CloudBees/src/CloudBeesProvider.php @@ -26,7 +26,7 @@ class CloudBeesProvider extends AbstractProvider implements Provider { - protected const NAME = 'CloudBeesProvider'; + protected static string $NAME = 'CloudBeesProvider'; private static ?CloudBeesProvider $instance = null; diff --git a/providers/CloudBees/tests/integration/CloudBeesProviderTest.php b/providers/CloudBees/tests/integration/CloudBeesProviderTest.php index 588d2d4f..5c4cf4f6 100644 --- a/providers/CloudBees/tests/integration/CloudBeesProviderTest.php +++ b/providers/CloudBees/tests/integration/CloudBeesProviderTest.php @@ -42,6 +42,7 @@ public function testCanBeInstantiated(): void $this->assertNotNull($instance); $this->assertInstanceOf(CloudBeesProvider::class, $instance); $this->assertInstanceOf(Provider::class, $instance); + $this->assertEquals('CloudBeesProvider', $instance->getMetadata()->getName()); } public function testCanResolveBool(): void diff --git a/providers/Flagd/src/FlagdProvider.php b/providers/Flagd/src/FlagdProvider.php index 171d25d1..cb72bc04 100644 --- a/providers/Flagd/src/FlagdProvider.php +++ b/providers/Flagd/src/FlagdProvider.php @@ -16,7 +16,7 @@ class FlagdProvider extends AbstractProvider implements Provider { - protected const NAME = 'FlagdProvider'; + protected static string $NAME = 'FlagdProvider'; private IConfig $config; diff --git a/providers/Flagd/tests/unit/FlagdProviderTest.php b/providers/Flagd/tests/unit/FlagdProviderTest.php index 8777e11b..2eca3114 100644 --- a/providers/Flagd/tests/unit/FlagdProviderTest.php +++ b/providers/Flagd/tests/unit/FlagdProviderTest.php @@ -35,6 +35,7 @@ public function testCanBeInstantiated(): void // Then $this->assertNotNull($instance); $this->assertInstanceOf(Provider::class, $instance); + $this->assertEquals('FlagdProvider', $instance->getMetadata()->getName()); } public function testCanInstantiateHttpWithConfigObject(): void diff --git a/providers/Split/src/SplitProvider.php b/providers/Split/src/SplitProvider.php index 9a4dc465..dee839fb 100644 --- a/providers/Split/src/SplitProvider.php +++ b/providers/Split/src/SplitProvider.php @@ -31,7 +31,7 @@ class SplitProvider extends AbstractProvider implements Provider { - protected const NAME = 'SplitProvider'; + protected static string $NAME = 'SplitProvider'; /** * The Split factory will only be created one time diff --git a/providers/Split/tests/unit/SplitProviderTest.php b/providers/Split/tests/unit/SplitProviderTest.php index a6db81b3..8302ef71 100644 --- a/providers/Split/tests/unit/SplitProviderTest.php +++ b/providers/Split/tests/unit/SplitProviderTest.php @@ -27,6 +27,7 @@ public function testCanBeInstantiated(): void // Then $this->assertNotNull($instance); $this->assertInstanceOf(Provider::class, $instance); + $this->assertEquals('SplitProvider', $instance->getMetadata()->getName()); } private function getPathToValidSplitFile(): string From 27d66c8acf65f48c1c32994f8840233aef78c9bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:26:53 -0400 Subject: [PATCH 70/90] chore(main): release open-feature/dd-trace-hook 0.2.0 (#84) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/DDTrace/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hooks/DDTrace/CHANGELOG.md b/hooks/DDTrace/CHANGELOG.md index 2f0349c2..20c703b4 100644 --- a/hooks/DDTrace/CHANGELOG.md +++ b/hooks/DDTrace/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/dd-trace-hook-0.2.0...open-feature/dd-trace-hook-0.2.0) (2024-08-05) + + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + ## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/dd-trace-hook-0.2.0...open-feature/dd-trace-hook-0.2.0) (2023-02-12) From 4ba0033dd08a2f9f2ab02ebd49b7b6e03d11eb79 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Tue, 3 Sep 2024 21:31:49 +0200 Subject: [PATCH 71/90] feat: new GO Feature Flag PHP provider (#106) * Exclude jetbrains IDE folder from GIT Signed-off-by: Thomas Poignant * Goff PHP Provider initial commit Signed-off-by: Thomas Poignant * fix linter issue Signed-off-by: Thomas Poignant * fix linter issue Signed-off-by: Thomas Poignant * removing phpcs cache file Signed-off-by: Thomas Poignant * Adding phpcs file to gitignore Signed-off-by: Thomas Poignant * Fix typo Signed-off-by: Thomas Poignant --------- Signed-off-by: Thomas Poignant Signed-off-by: Thomas Poignant --- .github/workflows/php-ci.yaml | 1 + .github/workflows/split_monorepo.yaml | 14 + .gitignore | 4 +- providers/GoFeatureFlag/.gitignore | 5 + providers/GoFeatureFlag/README.md | 144 ++++++ providers/GoFeatureFlag/composer.json | 123 +++++ providers/GoFeatureFlag/phpcs.xml.dist | 25 + providers/GoFeatureFlag/phpstan.neon.dist | 8 + providers/GoFeatureFlag/phpunit.xml.dist | 25 + providers/GoFeatureFlag/psalm-baseline.xml | 2 + providers/GoFeatureFlag/psalm.xml | 17 + .../src/GoFeatureFlagProvider.php | 154 ++++++ providers/GoFeatureFlag/src/config/Config.php | 60 +++ .../GoFeatureFlag/src/controller/OfrepApi.php | 149 ++++++ .../src/exception/BaseGoffException.php | 40 ++ .../src/exception/BaseOfrepException.php | 40 ++ .../src/exception/FlagNotFoundException.php | 26 + .../src/exception/InvalidConfigException.php | 24 + .../src/exception/InvalidContextException.php | 16 + .../src/exception/ParseException.php | 17 + .../src/exception/RateLimitedException.php | 18 + .../src/exception/UnauthorizedException.php | 18 + .../src/exception/UnknownOfrepException.php | 19 + .../src/model/OfrepApiErrorResponse.php | 46 ++ .../src/model/OfrepApiSuccessResponse.php | 82 +++ providers/GoFeatureFlag/src/util/Mapper.php | 36 ++ .../GoFeatureFlag/src/util/Validator.php | 132 +++++ providers/GoFeatureFlag/tests/TestCase.php | 39 ++ .../tests/unit/GoFeatureFlagProviderTest.php | 482 ++++++++++++++++++ .../tests/unit/controller/OfrepApiTest.php | 437 ++++++++++++++++ release-please-config.json | 4 + 31 files changed, 2206 insertions(+), 1 deletion(-) create mode 100644 providers/GoFeatureFlag/.gitignore create mode 100644 providers/GoFeatureFlag/README.md create mode 100644 providers/GoFeatureFlag/composer.json create mode 100644 providers/GoFeatureFlag/phpcs.xml.dist create mode 100644 providers/GoFeatureFlag/phpstan.neon.dist create mode 100644 providers/GoFeatureFlag/phpunit.xml.dist create mode 100644 providers/GoFeatureFlag/psalm-baseline.xml create mode 100644 providers/GoFeatureFlag/psalm.xml create mode 100644 providers/GoFeatureFlag/src/GoFeatureFlagProvider.php create mode 100644 providers/GoFeatureFlag/src/config/Config.php create mode 100644 providers/GoFeatureFlag/src/controller/OfrepApi.php create mode 100644 providers/GoFeatureFlag/src/exception/BaseGoffException.php create mode 100644 providers/GoFeatureFlag/src/exception/BaseOfrepException.php create mode 100644 providers/GoFeatureFlag/src/exception/FlagNotFoundException.php create mode 100644 providers/GoFeatureFlag/src/exception/InvalidConfigException.php create mode 100644 providers/GoFeatureFlag/src/exception/InvalidContextException.php create mode 100644 providers/GoFeatureFlag/src/exception/ParseException.php create mode 100644 providers/GoFeatureFlag/src/exception/RateLimitedException.php create mode 100644 providers/GoFeatureFlag/src/exception/UnauthorizedException.php create mode 100644 providers/GoFeatureFlag/src/exception/UnknownOfrepException.php create mode 100644 providers/GoFeatureFlag/src/model/OfrepApiErrorResponse.php create mode 100644 providers/GoFeatureFlag/src/model/OfrepApiSuccessResponse.php create mode 100644 providers/GoFeatureFlag/src/util/Mapper.php create mode 100644 providers/GoFeatureFlag/src/util/Validator.php create mode 100644 providers/GoFeatureFlag/tests/TestCase.php create mode 100644 providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php create mode 100644 providers/GoFeatureFlag/tests/unit/controller/OfrepApiTest.php diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml index 28eb2f9d..109afb1f 100644 --- a/.github/workflows/php-ci.yaml +++ b/.github/workflows/php-ci.yaml @@ -19,6 +19,7 @@ jobs: - hooks/Validators - providers/Flagd - providers/Split + - providers/GoFeatureFlag # - providers/CloudBees fail-fast: false diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index eac7db84..4d7e1caf 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -87,3 +87,17 @@ jobs: targetRepo: split-provider targetBranch: refs/tags/${{ github.event.release.tag_name }} filterArguments: '--subdirectory-filter providers/Split/ --force' + + split-provider-go-feature-flag: + runs-on: ubuntu-latest + steps: + - name: checkout + run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" + - name: push-provider-split + uses: tcarrio/git-filter-repo-docker-action@v1 + with: + privateKey: ${{ secrets.SSH_PRIVATE_KEY }} + targetOrg: open-feature-php + targetRepo: go-feature-flag-provider + targetBranch: refs/tags/${{ github.event.release.tag_name }} + filterArguments: '--subdirectory-filter providers/GoFeatureFlag/ --force' diff --git a/.gitignore b/.gitignore index b3f34e10..d3bb74fb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ composer.lock /proto/ -/.devenv* \ No newline at end of file +/.devenv* + +.idea/ \ No newline at end of file diff --git a/providers/GoFeatureFlag/.gitignore b/providers/GoFeatureFlag/.gitignore new file mode 100644 index 00000000..5c09088b --- /dev/null +++ b/providers/GoFeatureFlag/.gitignore @@ -0,0 +1,5 @@ +/composer.lock +/vendor +/build + +.php-cs-fixer.cache \ No newline at end of file diff --git a/providers/GoFeatureFlag/README.md b/providers/GoFeatureFlag/README.md new file mode 100644 index 00000000..13295546 --- /dev/null +++ b/providers/GoFeatureFlag/README.md @@ -0,0 +1,144 @@ +

+ go-feature-flag logo + +

+ +# GO Feature Flag - OpenFeature PHP provider +

+ + + Packagist Version + Documentation + Issues + Join us on slack +

+ +This repository contains the official PHP OpenFeature provider for accessing your feature flags with [GO Feature Flag](https://gofeatureflag.org). + +In conjunction with the [OpenFeature SDK](https://openfeature.dev/docs/reference/concepts/provider) you will be able +to evaluate your feature flags in your Ruby applications. + +For documentation related to flags management in GO Feature Flag, +refer to the [GO Feature Flag documentation website](https://gofeatureflag.org/docs). + +### Functionalities: +- Manage the integration of the OpenFeature PHP SDK and GO Feature Flag relay-proxy. + +## Dependency Setup + +### Composer + +```shell +composer require open-feature/go-feature-flag-provider +``` +## Getting started + +### Initialize the provider + +The `GoFeatureFlagProvider` takes a config object as parameter to be initialized. + +The constructor of the config object has the following options: + +| **Option** | **Description** | +|-----------------|------------------------------------------------------------------------------------------------------------------| +| `endpoint` | **(mandatory)** The URL to access to the relay-proxy.
*(example: `https://relay.proxy.gofeatureflag.org/`)* | +| `apiKey` | The token used to call the relay proxy. | +| `customHeaders` | Any headers you want to add to call the relay-proxy. | +| `httpclient` | The HTTP Client to use (if you want to use a custom one). _It has to be a `PSR-7` compliant implementation._ | + +The only required option to create a `GoFeatureFlagProvider` is the URL _(`endpoint`)_ to your GO Feature Flag relay-proxy instance. + +```php +use OpenFeature\Providers\GoFeatureFlag\config\Config; +use OpenFeature\Providers\GoFeatureFlag\GoFeatureFlagProvider; +use OpenFeature\implementation\flags\MutableEvaluationContext; +use OpenFeature\implementation\flags\Attributes; +use OpenFeature\OpenFeatureAPI; + +$config = new Config('http://gofeatureflag.org/', 'my-api-key'); +$provider = new GoFeatureFlagProvider($config); + +$api = OpenFeatureAPI::getInstance(); +$api->setProvider($provider); +$client = $api->getClient(); +$evaluationContext = new MutableEvaluationContext( + "214b796a-807b-4697-b3a3-42de0ec10a37", + new Attributes(["email" => 'contact@gofeatureflag.org']) + ); + +$value = $client->getBooleanDetails('integer_key', false, $evaluationContext); +if ($value) { + echo "The flag is enabled"; +} else { + echo "The flag is disabled"; +} +``` + +The evaluation context is the way for the client to specify contextual data that GO Feature Flag uses to evaluate the feature flags, it allows to define rules on the flag. + +The `targeting_key` is mandatory for GO Feature Flag to evaluate the feature flag, it could be the id of a user, a session ID or anything you find relevant to use as identifier during the evaluation. + + +### Evaluate a feature flag +The client is used to retrieve values for the current `EvaluationContext`. +For example, retrieving a boolean value for the flag **"my-flag"**: + +```php +$value = $client->getBooleanDetails('integer_key', false, $evaluationContext); +if ($value) { + echo "The flag is enabled"; +} else { + echo "The flag is disabled"; +} +``` + +GO Feature Flag supports different all OpenFeature supported types of feature flags, it means that you can use all the accessor directly +```php +// Bool +$client->getBooleanDetails('my-flag-key', false, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +$client->getBooleanValue('my-flag-key', false, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); + +// String +$client->getStringDetails('my-flag-key', "default", new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +$client->getStringValue('my-flag-key', "default", new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); + +// Integer +$client->getIntegerDetails('my-flag-key', 1, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +$client->getIntegerValue('my-flag-key', 1, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); + +// Float +$client->getFloatDetails('my-flag-key', 1.1, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +$client->getFloatValue('my-flag-key', 1.1, new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); + +// Object +$client->getObjectDetails('my-flag-key', ["default" => true], new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +$client->getObjectValue('my-flag-key', ["default" => true], new MutableEvaluationContext("214b796a-807b-4697-b3a3-42de0ec10a37")); +``` + +## Features status + +| Status | Feature | Description | +|-------|-----------------|----------------------------------------------------------------------------| +| ✅ | Flag evaluation | It is possible to evaluate all the type of flags | +| ❌ | Caching | Mechanism is in place to refresh the cache in case of configuration change | +| ❌ | Event Streaming | Not supported by the SDK | +| ❌ | Logging | Not supported by the SDK | +| ❌ | Flag Metadata | Not supported by the SDK | + + +**Implemented**: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ + +## Contributing +This project welcomes contributions from the community. +If you're interested in contributing, see the [contributors' guide](https://github.com/thomaspoignant/go-feature-flag/blob/main/CONTRIBUTING.md) for some helpful tips. + +### PHP Versioning +This library targets PHP version 8.0 and newer. As long as you have any compatible version of PHP on your system you should be able to utilize the OpenFeature SDK. + +This package also has a .tool-versions file for use with PHP version managers like asdf. + +### Installation and Dependencies +Install dependencies with `composer install`, it will update the `composer.lock` with the most recent compatible versions. + +We value having as few runtime dependencies as possible. The addition of any dependencies requires careful consideration and review. + diff --git a/providers/GoFeatureFlag/composer.json b/providers/GoFeatureFlag/composer.json new file mode 100644 index 00000000..3cf4f307 --- /dev/null +++ b/providers/GoFeatureFlag/composer.json @@ -0,0 +1,123 @@ +{ + "name": "open-feature/go-feature-flag-provider", + "description": "The GO Feature Flag provider package for open-feature", + "license": "Apache-2.0", + "type": "library", + "keywords": [ + "featureflags", + "featureflagging", + "openfeature", + "gofeatureflag", + "provider" + ], + "authors": [ + { + "name": "Thomas Poignant", + "homepage": "https://github.com/thomaspoignant/go-feature-flag" + } + ], + "require": { + "php": "^8", + "guzzlehttp/guzzle": "^7.9", + "open-feature/sdk": "^2.0", + "psr/http-message": "^2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "mockery/mockery": "^1.6", + "spatie/phpunit-snapshot-assertions": "^4.2", + "phan/phan": "^5.4", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "~1.10.0", + "phpstan/phpstan-mockery": "^1.0", + "phpstan/phpstan-phpunit": "^1.1", + "psalm/plugin-mockery": "^0.11.0", + "psalm/plugin-phpunit": "^0.18.0", + "ramsey/coding-standard": "^2.0.3", + "ramsey/composer-repl": "^1.4", + "ramsey/conventional-commits": "^1.3", + "roave/security-advisories": "dev-latest", + "spatie/phpunit-snapshot-assertions": "^4.2", + "vimeo/psalm": "~4.30.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "OpenFeature\\Providers\\GoFeatureFlag\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "OpenFeature\\Providers\\GoFeatureFlag\\Test\\": "tests/" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "captainhook/plugin-composer": true, + "ramsey/composer-repl": true + }, + "sort-packages": true + }, + "scripts": { + "dev:analyze": [ + "@dev:analyze:phpstan", + "@dev:analyze:psalm" + ], + "dev:analyze:phpstan": "phpstan --ansi --debug --memory-limit=512M", + "dev:analyze:psalm": "psalm", + "dev:build:clean": "git clean -fX build/", + "dev:lint": [ + "@dev:lint:syntax", + "@dev:lint:style" + ], + "dev:lint:fix": "phpcbf", + "dev:lint:style": "phpcs --colors", + "dev:lint:syntax": "parallel-lint --colors src/ tests/", + "dev:test": [ + "@dev:lint", + "@dev:analyze", + "@dev:test:unit", + "@dev:test:integration" + ], + "dev:test:coverage:ci": "phpunit --colors=always --coverage-text --coverage-clover build/coverage/clover.xml --coverage-cobertura build/coverage/cobertura.xml --coverage-crap4j build/coverage/crap4j.xml --coverage-xml build/coverage/coverage-xml --log-junit build/junit.xml", + "dev:test:coverage:html": "phpunit --colors=always --coverage-html build/coverage/coverage-html/", + "dev:test:unit": [ + "@dev:test:unit:setup", + "phpunit --colors=always --testdox --testsuite=unit", + "@dev:test:unit:teardown" + ], + "dev:test:unit:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:unit:setup": "echo 'Setup for unit tests...'", + "dev:test:unit:teardown": "echo 'Tore down for unit tests...'", + "dev:test:integration": [ + "@dev:test:integration:setup", + "phpunit --colors=always --testdox --testsuite=integration", + "@dev:test:integration:teardown" + ], + "dev:test:integration:debug": "phpunit --colors=always --testdox -d xdebug.profiler_enable=on", + "dev:test:integration:setup": "echo 'Setup for integration tests...'", + "dev:test:integration:teardown": "echo 'Tore down integration tests...'", + "test": "@dev:test" + }, + "scripts-descriptions": { + "dev:analyze": "Runs all static analysis checks.", + "dev:analyze:phpstan": "Runs the PHPStan static analyzer.", + "dev:analyze:psalm": "Runs the Psalm static analyzer.", + "dev:build:clean": "Cleans the build/ directory.", + "dev:lint": "Runs all linting checks.", + "dev:lint:fix": "Auto-fixes coding standards issues, if possible.", + "dev:lint:style": "Checks for coding standards issues.", + "dev:lint:syntax": "Checks for syntax errors.", + "dev:test": "Runs linting, static analysis, and unit tests.", + "dev:test:coverage:ci": "Runs unit tests and generates CI coverage reports.", + "dev:test:coverage:html": "Runs unit tests and generates HTML coverage report.", + "dev:test:unit": "Runs unit tests.", + "test": "Runs linting, static analysis, and unit tests." + } +} diff --git a/providers/GoFeatureFlag/phpcs.xml.dist b/providers/GoFeatureFlag/phpcs.xml.dist new file mode 100644 index 00000000..55d9d3a1 --- /dev/null +++ b/providers/GoFeatureFlag/phpcs.xml.dist @@ -0,0 +1,25 @@ + + + + + + + + ./src + ./tests + + */tests/fixtures/* + */tests/*/fixtures/* + + + + + + + + + + + + + diff --git a/providers/GoFeatureFlag/phpstan.neon.dist b/providers/GoFeatureFlag/phpstan.neon.dist new file mode 100644 index 00000000..000a4863 --- /dev/null +++ b/providers/GoFeatureFlag/phpstan.neon.dist @@ -0,0 +1,8 @@ +parameters: + tmpDir: ./build/cache/phpstan + level: max + paths: + - ./src + excludePaths: + - */tests/fixtures/* + - */tests/*/fixtures/* diff --git a/providers/GoFeatureFlag/phpunit.xml.dist b/providers/GoFeatureFlag/phpunit.xml.dist new file mode 100644 index 00000000..ecad4cce --- /dev/null +++ b/providers/GoFeatureFlag/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + + ./tests/unit + + + + + + ./src + + + + + + + + diff --git a/providers/GoFeatureFlag/psalm-baseline.xml b/providers/GoFeatureFlag/psalm-baseline.xml new file mode 100644 index 00000000..ceaa5778 --- /dev/null +++ b/providers/GoFeatureFlag/psalm-baseline.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/providers/GoFeatureFlag/psalm.xml b/providers/GoFeatureFlag/psalm.xml new file mode 100644 index 00000000..c3e6c03c --- /dev/null +++ b/providers/GoFeatureFlag/psalm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/providers/GoFeatureFlag/src/GoFeatureFlagProvider.php b/providers/GoFeatureFlag/src/GoFeatureFlagProvider.php new file mode 100644 index 00000000..e483119a --- /dev/null +++ b/providers/GoFeatureFlag/src/GoFeatureFlagProvider.php @@ -0,0 +1,154 @@ +getCustomHeaders())) { + $config->addCustomHeader('Content-Type', 'application/json'); + } + $this->ofrepApi = new OfrepApi($config); + } + + public function getMetadata(): Metadata + { + return new Metadata(static::$NAME); + } + + public function resolveBooleanValue(string $flagKey, bool $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + { + return $this->evaluate($flagKey, $defaultValue, ['boolean'], $context); + } + + /** + * @param array|array|bool|DateTime|float|int|string|null $defaultValue + * @param array $allowedClasses + */ + private function evaluate(string $flagKey, array | string | bool | DateTime | float | int | null $defaultValue, array $allowedClasses, ?EvaluationContext $evaluationContext = null): ResolutionDetails + { + try { + Validator::validateFlagKey($flagKey); + + if ($evaluationContext === null) { + throw new InvalidContextException('Evaluation context is null'); + } + if ($evaluationContext->getTargetingKey() === null || $evaluationContext->getTargetingKey() === '') { + throw new InvalidContextException('Missing targetingKey in evaluation context'); + } + + $apiResp = $this->ofrepApi->evaluate($flagKey, $evaluationContext); + + if ($apiResp instanceof OfrepApiErrorResponse) { + $err = new ResolutionError( + $apiResp->getErrorCode(), + $apiResp->getErrorDetails(), + ); + + return (new ResolutionDetailsBuilder()) + ->withValue($defaultValue) + ->withError($err) + ->withReason($apiResp->getReason()) + ->build(); + } + + if (!$this->isValidType($apiResp->getValue(), $allowedClasses)) { + return (new ResolutionDetailsBuilder()) + ->withReason(Reason::ERROR) + ->withError(new ResolutionError( + ErrorCode::TYPE_MISMATCH(), + "Invalid type for $flagKey, got " . gettype($apiResp->getValue()) . ' expected ' . implode(', ', $allowedClasses), + )) + ->withValue($defaultValue) + ->build(); + } + + return (new ResolutionDetailsBuilder()) + ->withValue($apiResp->getValue()) + ->withReason($apiResp->getReason()) + ->withVariant($apiResp->getVariant()) + ->build(); + } catch (BaseOfrepException $e) { + $err = new ResolutionError($e->getErrorCode(), $e->getMessage()); + + return (new ResolutionDetailsBuilder()) + ->withValue($defaultValue) + ->withError($err) + ->withReason(Reason::ERROR) + ->build(); + } catch (Throwable $e) { + return (new ResolutionDetailsBuilder()) + ->withValue($defaultValue) + ->withError(new ResolutionError(ErrorCode::GENERAL(), 'An error occurred while evaluating the flag: ' . $e->getMessage())) + ->withReason(Reason::ERROR) + ->build(); + } + } + + /** + * @param array $allowedClasses + */ + private function isValidType(mixed $value, array $allowedClasses): bool + { + foreach ($allowedClasses as $class) { + if ($value instanceof $class || gettype($value) === $class) { + return true; + } + } + + return false; + } + + public function resolveStringValue(string $flagKey, string $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + { + return $this->evaluate($flagKey, $defaultValue, ['string'], $context); + } + + public function resolveIntegerValue(string $flagKey, int $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + { + return $this->evaluate($flagKey, $defaultValue, ['integer'], $context); + } + + public function resolveFloatValue(string $flagKey, float $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + { + return $this->evaluate($flagKey, $defaultValue, ['double'], $context); + } + + public function resolveObjectValue(string $flagKey, mixed $defaultValue, ?EvaluationContext $context = null): ResolutionDetails + { + return $this->evaluate($flagKey, $defaultValue, ['array'], $context); + } +} diff --git a/providers/GoFeatureFlag/src/config/Config.php b/providers/GoFeatureFlag/src/config/Config.php new file mode 100644 index 00000000..510bc9e1 --- /dev/null +++ b/providers/GoFeatureFlag/src/config/Config.php @@ -0,0 +1,60 @@ + + */ + private array $customHeaders = []; + + /** + * @var ClientInterface|null - The HTTP Client to use (if you want to use a custom one) + */ + private ?ClientInterface $httpclient; + + /** + * @param string $endpoint - The endpoint to your GO Feature Flag Instance + * @param string|null $apiKey - API Key to use to connect to GO Feature Flag + * @param array|null $customHeaders - Custom headers you want to send + * @param ClientInterface|null $httpclient - The HTTP Client to use (if you want to use a custom one) + */ + public function __construct(string $endpoint, ?string $apiKey = '', ?array $customHeaders = [], ?ClientInterface $httpclient = null) + { + $this->httpclient = $httpclient; + $this->endpoint = $endpoint; + $this->customHeaders = $customHeaders ?? []; + if ($apiKey !== null && $apiKey !== '') { + $this->customHeaders['Authorization'] = 'Bearer ' . $apiKey; + } + } + + public function getEndpoint(): string + { + return $this->endpoint; + } + + /** + * @return array + */ + public function getCustomHeaders(): array + { + return $this->customHeaders; + } + + public function addCustomHeader(string $key, string $value): void + { + $this->customHeaders[$key] = $value; + } + + public function getHttpClient(): ?ClientInterface + { + return $this->httpclient; + } +} diff --git a/providers/GoFeatureFlag/src/controller/OfrepApi.php b/providers/GoFeatureFlag/src/controller/OfrepApi.php new file mode 100644 index 00000000..d5d17edb --- /dev/null +++ b/providers/GoFeatureFlag/src/controller/OfrepApi.php @@ -0,0 +1,149 @@ +options = $config; + $this->client = $config->getHttpClient() ?? new Client([ + 'base_uri' => $config->getEndpoint(), + ]); + } + + /** + * @throws ParseException + * @throws FlagNotFoundException + * @throws RateLimitedException + * @throws UnauthorizedException + * @throws UnknownOfrepException + * @throws BaseOfrepException + */ + public function evaluate(string $flagKey, EvaluationContext $evaluationContext): OfrepApiSuccessResponse | OfrepApiErrorResponse + { + try { + if ($this->retryAfter !== null) { + if (time() < $this->retryAfter) { + throw new RateLimitedException(); + } else { + $this->retryAfter = null; + } + } + + $baseUri = $this->options->getEndpoint(); + $evaluateApiPath = rtrim($baseUri, '/') . "/ofrep/v1/evaluate/flags/{$flagKey}"; + $headers = array_merge( + ['Content-Type' => 'application/json'], + $this->options->getCustomHeaders(), + ); + + $fields = array_merge( + $evaluationContext->getAttributes()->toArray(), + ['targetingKey' => $evaluationContext->getTargetingKey()], + ); + + $requestBody = json_encode(['context' => $fields]); + if ($requestBody === false) { + throw new ParseException('failed to encode request body'); + } + $req = new Request('POST', $evaluateApiPath, $headers, $requestBody); + $response = $this->client->sendRequest($req); + + switch ($response->getStatusCode()) { + case 200: + return $this->parseSuccessResponse($response); + case 400: + return $this->parseErrorResponse($response); + case 401: + case 403: + throw new UnauthorizedException($response); + case 404: + throw new FlagNotFoundException($flagKey, $response); + case 429: + $this->parseRetryLaterHeader($response); + + throw new RateLimitedException($response); + default: + throw new UnknownOfrepException($response); + } + } catch (BaseOfrepException $e) { + throw $e; + } catch (GuzzleException | Throwable $e) { + echo $e; + + throw new UnknownOfrepException(null, $e); + } + } + + /** + * @throws ParseException + */ + private function parseSuccessResponse(ResponseInterface $response): OfrepApiSuccessResponse + { + /** @var array $parsed */ + $parsed = json_decode($response->getBody()->getContents(), true); + $parsed = Validator::validateSuccessApiResponse($parsed); + + return new OfrepApiSuccessResponse($parsed); + } + + /** + * @throws ParseException + */ + private function parseErrorResponse(ResponseInterface $response): OfrepApiErrorResponse + { + /** @var array $parsed */ + $parsed = json_decode($response->getBody()->getContents(), true); + $parsed = Validator::validateErrorApiResponse($parsed); + + return new OfrepApiErrorResponse($parsed); + } + + private function parseRetryLaterHeader(ResponseInterface $response): void + { + $retryAfterHeader = $response->getHeaderLine('Retry-After'); + if ($retryAfterHeader) { + if (is_numeric($retryAfterHeader)) { + // Retry-After is in seconds + $this->retryAfter = time() + (int) $retryAfterHeader; + } else { + // Retry-After is in HTTP-date format + $retryTime = strtotime($retryAfterHeader); + $this->retryAfter = $retryTime !== false ? $retryTime : null; + } + } + } +} diff --git a/providers/GoFeatureFlag/src/exception/BaseGoffException.php b/providers/GoFeatureFlag/src/exception/BaseGoffException.php new file mode 100644 index 00000000..cc2221f3 --- /dev/null +++ b/providers/GoFeatureFlag/src/exception/BaseGoffException.php @@ -0,0 +1,40 @@ +customMessage = $message; + $this->response = $response; + $this->errorCode = $errorCode; + parent::__construct($message, $code, $previous); + } + + public function getCustomMessage(): string + { + return $this->customMessage; + } + + public function getResponse(): ?ResponseInterface + { + return $this->response; + } + + public function getErrorCode(): ErrorCode + { + return $this->errorCode; + } +} diff --git a/providers/GoFeatureFlag/src/exception/BaseOfrepException.php b/providers/GoFeatureFlag/src/exception/BaseOfrepException.php new file mode 100644 index 00000000..fa33d8ae --- /dev/null +++ b/providers/GoFeatureFlag/src/exception/BaseOfrepException.php @@ -0,0 +1,40 @@ +customMessage = $message; + $this->response = $response; + $this->errorCode = $errorCode; + parent::__construct($message, $code, $previous); + } + + public function getCustomMessage(): string + { + return $this->customMessage; + } + + public function getResponse(): ?ResponseInterface + { + return $this->response; + } + + public function getErrorCode(): ErrorCode + { + return $this->errorCode; + } +} diff --git a/providers/GoFeatureFlag/src/exception/FlagNotFoundException.php b/providers/GoFeatureFlag/src/exception/FlagNotFoundException.php new file mode 100644 index 00000000..caf3b200 --- /dev/null +++ b/providers/GoFeatureFlag/src/exception/FlagNotFoundException.php @@ -0,0 +1,26 @@ +flagKey = $flagKey; + $message = "Flag with key $flagKey not found"; + $code = 1002; + parent::__construct($message, ErrorCode::FLAG_NOT_FOUND(), $response, $code); + } + + public function getFlagKey(): string + { + return $this->flagKey; + } +} diff --git a/providers/GoFeatureFlag/src/exception/InvalidConfigException.php b/providers/GoFeatureFlag/src/exception/InvalidConfigException.php new file mode 100644 index 00000000..0458c706 --- /dev/null +++ b/providers/GoFeatureFlag/src/exception/InvalidConfigException.php @@ -0,0 +1,24 @@ +customMessage = $message; + parent::__construct($message, $code, $previous); + } + + public function getCustomMessage(): string + { + return $this->customMessage; + } +} diff --git a/providers/GoFeatureFlag/src/exception/InvalidContextException.php b/providers/GoFeatureFlag/src/exception/InvalidContextException.php new file mode 100644 index 00000000..fbaf00b4 --- /dev/null +++ b/providers/GoFeatureFlag/src/exception/InvalidContextException.php @@ -0,0 +1,16 @@ + $apiData + * + * @throws ParseException + */ + public function __construct(array $apiData) + { + $this->reason = Reason::ERROR; + $this->errorCode = Mapper::errorCode(is_string($apiData['errorCode']) ? $apiData['errorCode'] : ''); + $this->errorDetails = is_string($apiData['errorDetails']) ? $apiData['errorDetails'] : ''; + } + + public function getReason(): string + { + return $this->reason; + } + + public function getErrorCode(): ErrorCode + { + return $this->errorCode; + } + + public function getErrorDetails(): string + { + return $this->errorDetails; + } +} diff --git a/providers/GoFeatureFlag/src/model/OfrepApiSuccessResponse.php b/providers/GoFeatureFlag/src/model/OfrepApiSuccessResponse.php new file mode 100644 index 00000000..7e8d6555 --- /dev/null +++ b/providers/GoFeatureFlag/src/model/OfrepApiSuccessResponse.php @@ -0,0 +1,82 @@ +|array|bool|DateTime|float|int|string|null + */ + private array | bool | DateTime | float | int | string | null $value; + private string $reason; + private string $variant; + + // TODO: Commenting Metadata here because it is not supported by the SDK yet. + // private array $metadata; + + /** + * @param array $apiData + * + * @throws ParseException + */ + public function __construct( + array $apiData, + ) { + if ( + is_null($apiData['value']) + || is_array($apiData['value']) + || is_bool($apiData['value']) + || $apiData['value'] instanceof DateTime + || is_float($apiData['value']) + || is_int($apiData['value']) + || is_string($apiData['value']) + ) { + $this->value = $apiData['value']; + } else { + throw new ParseException('Invalid type for value'); + } + + $this->variant = is_string($apiData['variant']) ? $apiData['variant'] : 'error in provider'; + $this->reason = Mapper::reason(is_string($apiData['reason']) ? $apiData['reason'] : ''); + // $this->metadata = $apiData['metadata'] ?? []; + } + + /** + * @return array|array|bool|DateTime|float|int|string|null + */ + public function getValue(): array | bool | DateTime | float | int | string | null + { + return $this->value; + } + + public function getReason(): string + { + return $this->reason; + } + + public function getVariant(): string + { + return $this->variant; + } + + // /** + // * @return array + // */ + // public function getMetadata(): array + // { + // return $this->metadata; + // } +} diff --git a/providers/GoFeatureFlag/src/util/Mapper.php b/providers/GoFeatureFlag/src/util/Mapper.php new file mode 100644 index 00000000..6d55f97d --- /dev/null +++ b/providers/GoFeatureFlag/src/util/Mapper.php @@ -0,0 +1,36 @@ + ErrorCode::PROVIDER_NOT_READY(), + 'FLAG_NOT_FOUND' => ErrorCode::FLAG_NOT_FOUND(), + 'PARSE_ERROR' => ErrorCode::PARSE_ERROR(), + 'TYPE_MISMATCH' => ErrorCode::TYPE_MISMATCH(), + 'TARGETING_KEY_MISSING' => ErrorCode::TARGETING_KEY_MISSING(), + 'INVALID_CONTEXT' => ErrorCode::INVALID_CONTEXT(), + default => ErrorCode::GENERAL() + }; + } + + public static function reason(string $reason): string + { + return match ($reason) { + 'ERROR' => Reason::ERROR, + 'DEFAULT' => Reason::DEFAULT, + 'TARGETING_MATCH' => Reason::TARGETING_MATCH, + 'SPLIT' => Reason::SPLIT, + 'DISABLED' => Reason::DISABLED, + default => Reason::UNKNOWN + }; + } +} diff --git a/providers/GoFeatureFlag/src/util/Validator.php b/providers/GoFeatureFlag/src/util/Validator.php new file mode 100644 index 00000000..37bc62d1 --- /dev/null +++ b/providers/GoFeatureFlag/src/util/Validator.php @@ -0,0 +1,132 @@ +getEndpoint()); + } + + /** + * @param string $endpoint - The endpoint to validate + * + * @throws InvalidConfigException + */ + private static function validateEndpoint(string $endpoint): void + { + if (!filter_var($endpoint, FILTER_VALIDATE_URL)) { + throw new InvalidConfigException('Invalid endpoint URL: ' . $endpoint); + } + } + + /** + * @param mixed $data - The data to validate + * + * @return array{key: string, reason: string, variant: string} + * + * @throws ParseException + */ + public static function validateSuccessApiResponse(mixed $data): array + { + if (!is_array($data)) { + throw new ParseException('invalid json object, expected associative array'); + } + + $requiredKeys = ['key', 'value', 'reason', 'variant']; + $missingKeys = array_diff($requiredKeys, array_keys($data)); + if (count($missingKeys) > 0) { + throw new ParseException( + 'missing keys in the success response: ' . implode(', ', $missingKeys), + ); + } + + if (!is_string($data['key'])) { + throw new ParseException('key is not a string'); + } + + if (!is_string($data['variant'])) { + throw new ParseException('variant is not a string'); + } + + if (!is_string($data['reason'])) { + throw new ParseException('reason is not a string'); + } + + if (key_exists('metadata', $data) && !is_array($data['metadata'])) { + throw new ParseException('metadata is not an array'); + } + + return $data; + } + + /** + * @param mixed $data - The data to validate + * + * @return array{errorCode: string} + * + * @throws ParseException + */ + public static function validateErrorApiResponse(mixed $data): array + { + if (!is_array($data)) { + throw new ParseException('invalid json object, expected associative array'); + } + + $requiredKeys = ['key', 'errorCode']; + $missingKeys = array_diff($requiredKeys, array_keys($data)); + if (count($missingKeys) > 0) { + throw new ParseException( + 'missing keys in the error response: ' . implode(', ', $missingKeys), + ); + } + + if (!is_string($data['errorCode'])) { + throw new ParseException('key is not a string', null); + } + + if (key_exists('errorDetails', $data) && !is_string($data['errorDetails'])) { + throw new ParseException('errorDetails is not a string', null); + } + + return $data; + } + + /** + * @param string $flagKey - The flag key to validate + * + * @throws InvalidConfigException + */ + public static function validateFlagKey(string $flagKey): void + { + if ($flagKey === '') { + throw new InvalidConfigException('Flag key is null or empty'); + } + } +} diff --git a/providers/GoFeatureFlag/tests/TestCase.php b/providers/GoFeatureFlag/tests/TestCase.php new file mode 100644 index 00000000..9d7a833b --- /dev/null +++ b/providers/GoFeatureFlag/tests/TestCase.php @@ -0,0 +1,39 @@ + $class + * @param mixed ...$arguments + * + * @return T & MockInterface + * + * @template T + * + * phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + */ + public function mockery(string $class, ...$arguments) + { + /** @var T & MockInterface $mock */ + $mock = Mockery::mock($class, ...$arguments); + + return $mock; + } +} diff --git a/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php b/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php new file mode 100644 index 00000000..e990ec90 --- /dev/null +++ b/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php @@ -0,0 +1,482 @@ +expectException(InvalidConfigException::class); + new GoFeatureFlagProvider( + new Config('invalid'), + ); + } + + // Configuration validation tests + + public function testShouldNotThrowIfValidEndpoint(): void + { + $provider = new GoFeatureFlagProvider( + new Config('https://gofeatureflag.org/'), + ); + $this->assertInstanceOf(GoFeatureFlagProvider::class, $provider); + } + + public function testShouldRaiseIfEndpointIsNotHttp(): void + { + $this->expectException(InvalidConfigException::class); + $provider = new GoFeatureFlagProvider( + new Config('gofeatureflag.org'), + ); + $this->assertInstanceOf(GoFeatureFlagProvider::class, $provider); + } + + public function testEmptyEndpointShouldThrow(): void + { + $this->expectException(InvalidConfigException::class); + new GoFeatureFlagProvider( + new Config(''), + ); + } + + public function testMetadataNameIsDefined(): void + { + $config = new Config('http://localhost:1031/'); + $provider = new GoFeatureFlagProvider($config); + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + assertEquals('GO Feature Flag Provider', $api->getProviderMetadata()->getName()); + } + + // Metadata tests + + public function testShouldReturnTheValueOfTheFlagAsInt(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getIntegerDetails('integer_key', 1, $this->defaultEvaluationContext); + assertEquals(42, $got->getValue()); + assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + assertEquals('default', $got->getVariant()); + assertEquals(null, $got->getError()); + assertEquals('integer_key', $got->getFlagKey()); + } + + /** + * @throws ReflectionException + */ + private function mockHttpClient(GoFeatureFlagProvider $provider, MockObject $mockClient): void + { + $providerReflection = new ReflectionClass($provider); + $ofrepApiProperty = $providerReflection->getProperty('ofrepApi'); + $ofrepApiProperty->setAccessible(true); + $ofrepApi = $ofrepApiProperty->getValue($provider); + + $ofrepApiReflection = new ReflectionClass($ofrepApi); + $clientProperty = $ofrepApiReflection->getProperty('client'); + $clientProperty->setAccessible(true); + $clientProperty->setValue($ofrepApi, $mockClient); + } + + public function testShouldReturnTheValueOfTheFlagAsFloat(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flag-key', + 'value' => 42.2, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getFloatDetails('flag-key', 1.0, $this->defaultEvaluationContext); + assertEquals(42.2, $got->getValue()); + assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + assertEquals('default', $got->getVariant()); + assertEquals(null, $got->getError()); + assertEquals('flag-key', $got->getFlagKey()); + } + + public function testShouldReturnTheValueOfTheFlagAsString(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flag-key', + 'value' => 'value as string', + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getStringDetails('flag-key', 'default', $this->defaultEvaluationContext); + assertEquals('value as string', $got->getValue()); + assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + assertEquals('default', $got->getVariant()); + assertEquals(null, $got->getError()); + assertEquals('flag-key', $got->getFlagKey()); + } + + public function testShouldReturnTheValueOfTheFlagAsBool(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flag-key', + 'value' => true, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('flag-key', false, $this->defaultEvaluationContext); + assertEquals(true, $got->getValue()); + assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + assertEquals('default', $got->getVariant()); + assertEquals(null, $got->getError()); + assertEquals('flag-key', $got->getFlagKey()); + } + + public function testShouldReturnTheValueOfTheFlagAsObject(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flag-key', + 'value' => ['value' => 'value as object'], + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getObjectDetails('flag-key', ['default' => true], $this->defaultEvaluationContext); + assertEquals(['value' => 'value as object'], $got->getValue()); + assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + assertEquals('default', $got->getVariant()); + assertEquals(null, $got->getError()); + assertEquals('flag-key', $got->getFlagKey()); + } + + public function testShouldReturnTheDefaultValueIfFlagIsNotTheRightType(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('integer_key', false, $this->defaultEvaluationContext); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::TYPE_MISMATCH(), $got->getError()->getResolutionErrorCode()); + assertEquals('Invalid type for integer_key, got integer expected boolean', $got->getError()->getResolutionErrorMessage()); + assertEquals('integer_key', $got->getFlagKey()); + } + + public function testShouldReturnTheDefaultValueOfTheFlagIfErrorSendByTheAPIHttpCode403(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(403, [], json_encode([])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_key', false, $this->defaultEvaluationContext); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::GENERAL(), $got->getError()->getResolutionErrorCode()); + assertEquals('Unauthorized access to the API', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_key', $got->getFlagKey()); + } + + public function testShouldReturnTheDefaultValueOfTheFlagIfErrorSendByTheAPIHttpCode400(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(400, [], json_encode([ + 'key' => 'integer_key', + 'reason' => 'ERROR', + 'errorCode' => 'INVALID_CONTEXT', + 'errorDetails' => 'Error Details for invalid context', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_key', false, $this->defaultEvaluationContext); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::INVALID_CONTEXT(), $got->getError()->getResolutionErrorCode()); + assertEquals('Error Details for invalid context', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_key', $got->getFlagKey()); + } + + public function testShouldReturnDefaultValueIfNoEvaluationContext(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_key', false); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::INVALID_CONTEXT(), $got->getError()->getResolutionErrorCode()); + assertEquals('Missing targetingKey in evaluation context', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_key', $got->getFlagKey()); + } + + public function testShouldReturnDefaultValueIfEvaluationContextHasEmptyStringTargetingKey(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_key', false, new MutableEvaluationContext('')); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::INVALID_CONTEXT(), $got->getError()->getResolutionErrorCode()); + assertEquals('Missing targetingKey in evaluation context', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_key', $got->getFlagKey()); + } + + public function testShouldReturnDefaultValueIfEvaluationContextHasNullTargetingKey(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_key', false, new MutableEvaluationContext(null)); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::INVALID_CONTEXT(), $got->getError()->getResolutionErrorCode()); + assertEquals('Missing targetingKey in evaluation context', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_key', $got->getFlagKey()); + } + + public function testShouldReturnDefaultValueIfFlagKeyEmptyString(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $mockClient->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('', false, $this->defaultEvaluationContext); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::GENERAL(), $got->getError()->getResolutionErrorCode()); + assertEquals('An error occurred while evaluating the flag: Flag key is null or empty', $got->getError()->getResolutionErrorMessage()); + assertEquals('', $got->getFlagKey()); + } + + public function testReturnAnErrorAPIResponseIf500(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(500, [], json_encode([])); + + $mockClient + ->expects($this->once()) + ->method('sendRequest') + ->willReturn($mockResponse); + + $config = new Config('http://gofeatureflag.org/'); + $provider = new GoFeatureFlagProvider($config); + + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $got = $client->getBooleanDetails('boolean_flag', false, $this->defaultEvaluationContext); + assertEquals(false, $got->getValue()); + assertEquals(Reason::ERROR, $got->getReason()); + assertEquals(null, $got->getVariant()); + assertEquals(ErrorCode::GENERAL(), $got->getError()->getResolutionErrorCode()); + assertEquals('Unknown error occurred', $got->getError()->getResolutionErrorMessage()); + assertEquals('boolean_flag', $got->getFlagKey()); + } + + protected function setUp(): void + { + parent::setUp(); + $this->defaultEvaluationContext = new MutableEvaluationContext('214b796a-807b-4697-b3a3-42de0ec10a37', new Attributes(['email' => 'contact@gofeatureflag.org'])); + } +} diff --git a/providers/GoFeatureFlag/tests/unit/controller/OfrepApiTest.php b/providers/GoFeatureFlag/tests/unit/controller/OfrepApiTest.php new file mode 100644 index 00000000..8caa13f7 --- /dev/null +++ b/providers/GoFeatureFlag/tests/unit/controller/OfrepApiTest.php @@ -0,0 +1,437 @@ +expectException(RateLimitedException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(429, [], json_encode([])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIfNotAuthorized401() + { + $this->expectException(UnauthorizedException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(401, [], json_encode([])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIfNotAuthorized403() + { + $this->expectException(UnauthorizedException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(403, [], json_encode([])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIfFlagNotFound404() + { + $this->expectException(FlagNotFoundException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(404, [], json_encode([])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIfUnknownHttpCode500() + { + $this->expectException(UnknownOfrepException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(500, [], json_encode([])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldReturnAnErrorResponseIf400() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(400, [], json_encode([ + 'key' => 'flagKey', + 'errorCode' => 'TYPE_MISMATCH', + 'errorDetails' => 'The flag value is not of the expected type', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $got = $api->evaluate('flagKey', $this->defaultEvaluationContext); + $this->assertInstanceOf(OfrepApiErrorResponse::class, $got); + $this->assertEquals(Reason::ERROR, $got->getReason()); + $this->assertEquals(ErrorCode::TYPE_MISMATCH(), $got->getErrorCode()); + $this->assertEquals('The flag value is not of the expected type', $got->getErrorDetails()); + } + + public function testShouldReturnAValidResponseIf200() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $got = $api->evaluate('flagKey', $this->defaultEvaluationContext); + $this->assertInstanceOf(OfrepApiSuccessResponse::class, $got); + $this->assertEquals(Reason::TARGETING_MATCH, $got->getReason()); + $this->assertEquals(true, $got->getValue()); + } + + public function testShouldRaiseAnErrorIf200AndJsonDoesNotContainTheRequiredKeysMissingValue() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIf200AndJsonDoesNotContainTheRequiredKeysMissingKey() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIf200AndJsonDoesNotContainTheRequiredKeysMissingReason() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIf200AndJsonDoesNotContainTheRequiredKeysMissingVariant() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIf400AndJsonDoesNotContainTheRequiredKeysMissingKey() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(400, [], json_encode([ + 'errorCode' => 'TYPE_MISMATCH', + 'errorDetails' => 'The flag value is not of the expected type', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldRaiseAnErrorIf400AndJsonDoesNotContainTheRequiredKeysMissingErrorCode() + { + $this->expectException(ParseException::class); + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(400, [], json_encode([ + 'key' => 'flagKey', + 'errorDetails' => 'The flag value is not of the expected type', + ])); + $mockClient->method('sendRequest')->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + public function testShouldNotBeAbleToCallTheApiAgainIfRateLimitedWithRetryAfterInt() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(429, ['Retry-After' => '1'], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->expects($this->exactly(1)) + ->method('sendRequest') + ->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + try { + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + + try { + $api->evaluate('another-flag', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + } + + public function testShouldBeAbleToCallTheApiAgainIfWeWaitAfterTheRetryAfterAsInt() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponseRateLimited = new Response(429, ['Retry-After' => '1'], json_encode([])); + $mockResponseSuccess = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->will($this->onConsecutiveCalls($mockResponseRateLimited, $mockResponseSuccess)); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + try { + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + + // Wait for 1.5 seconds + usleep(1500000); + + $got = $api->evaluate('another-flag', $this->defaultEvaluationContext); + $this->assertInstanceOf(OfrepApiSuccessResponse::class, $got); + } + + public function testShouldNotBeAbleToCallTheApiAgainIfRateLimitedWithRetryAfterDate() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(429, ['Retry-After' => gmdate('D, d M Y H:i:s \G\M\T', time() + 1)], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->expects($this->exactly(1)) + ->method('sendRequest') + ->willReturn($mockResponse); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + try { + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + + try { + $api->evaluate('another-flag', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + } + + public function testShouldBeAbleToCallTheApiAgainIfWeWaitAfterTheRetryAfterAsDate() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponseRateLimited = new Response(429, ['Retry-After' => gmdate('D, d M Y H:i:s \G\M\T', time() + 1)], json_encode([])); + $mockResponseSuccess = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + $mockClient->method('sendRequest')->will($this->onConsecutiveCalls($mockResponseRateLimited, $mockResponseSuccess)); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + try { + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } catch (RateLimitedException $e) { + $this->assertInstanceOf(RateLimitedException::class, $e); + } + + // Wait for 1.5 seconds + usleep(1500000); + + $got = $api->evaluate('another-flag', $this->defaultEvaluationContext); + $this->assertInstanceOf(OfrepApiSuccessResponse::class, $got); + } + + public function testShouldHaveAuthorizationHeaderIfApiKeyInConfig() + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'flagKey', + 'value' => true, + 'reason' => Reason::TARGETING_MATCH, + 'variant' => 'default', + ])); + + $mockClient->expects($this->once()) + ->method('sendRequest') + ->willReturnCallback(function ($req) use ($mockResponse) { + $this->assertArrayHasKey('Authorization', $req->getHeaders()); + $this->assertEquals('Bearer your-secure-api-key', $req->getHeader('Authorization')[0]); + + return $mockResponse; + }); + + $api = new OfrepApi(new Config('https://gofeatureflag.org/', apiKey: 'your-secure-api-key')); + $reflection = new ReflectionClass($api); + $property = $reflection->getProperty('client'); + $property->setAccessible(true); + $property->setValue($api, $mockClient); + + $api->evaluate('flagKey', $this->defaultEvaluationContext); + } + + protected function setUp(): void + { + parent::setUp(); + $this->defaultEvaluationContext = new MutableEvaluationContext('214b796a-807b-4697-b3a3-42de0ec10a37'); + } +} diff --git a/release-please-config.json b/release-please-config.json index a7d73257..84279a5e 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -29,6 +29,10 @@ "providers/Split": { "package-name": "open-feature/split-provider", "release-as": "0.3.0" + }, + "providers/GoFeatureFlag": { + "package-name": "open-feature/go-feature-flag-provider", + "release-as": "0.1.0" } } } From 9f1f9f9a50dd368f33bdf42eba076fac0e630faa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 21:33:28 +0200 Subject: [PATCH 72/90] chore(main): release open-feature/go-feature-flag-provider 0.1.0 (#108) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 3 ++- providers/GoFeatureFlag/CHANGELOG.md | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 providers/GoFeatureFlag/CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3bbbd594..c28141e7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,5 +4,6 @@ "hooks/Validators": "0.2.0", "providers/CloudBees": "0.3.0", "providers/Flagd": "0.4.0", - "providers/Split": "0.3.0" + "providers/Split": "0.3.0", + "providers/GoFeatureFlag": "0.1.0" } \ No newline at end of file diff --git a/providers/GoFeatureFlag/CHANGELOG.md b/providers/GoFeatureFlag/CHANGELOG.md new file mode 100644 index 00000000..699fd8f0 --- /dev/null +++ b/providers/GoFeatureFlag/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +## 0.1.0 (2024-09-03) + + +### Features + +* new GO Feature Flag PHP provider ([#106](https://github.com/open-feature/php-sdk-contrib/issues/106)) ([4ba0033](https://github.com/open-feature/php-sdk-contrib/commit/4ba0033dd08a2f9f2ab02ebd49b7b6e03d11eb79)) From fb4da77390493a5214c3241f1d747b8f2eecd9ec Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Tue, 3 Sep 2024 23:13:12 -0400 Subject: [PATCH 73/90] ci: use new git-filter-repo based action with tag filtering support for splitting monorepo to PHP packages (#110) * feat: support for splitting all repos including GoFeatureFlag from single matrix ci: support for running from split branch chore: remove outdated gitsplit config fix: tag rename rule chore: debug info postcheckout chore: disable all but one in matrix for validation ci: fix closing str ci: fix reference to subdir feat: push implicit tags from prefilter operation chore: update to latest fixed action chore: empty commit bump chore: update to tag output version of action fix: tag reference has package type as suffix before version ci: revert versions to next major to support new deployment structure ci: revert versions to next major to support new deployment structure chore: bump to latest version of action ci: pass reference for targetBranch or nothing if not provided ci: execute from releases only Signed-off-by: Tom Carrio * ci: support for conditionally executing matrix steps if tags are relevant Signed-off-by: Tom Carrio --------- Signed-off-by: Tom Carrio --- .github/workflows/split_monorepo.yaml | 152 +++++++++++--------------- .gitsplit.yml | 28 ----- .release-please-manifest.json | 14 +-- release-please-config.json | 14 +-- 4 files changed, 75 insertions(+), 133 deletions(-) delete mode 100644 .gitsplit.yml diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index 4d7e1caf..f51f260f 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -2,102 +2,72 @@ name: split-monorepo on: release: types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Package tag' + type: string + required: true jobs: - split-hook-dd-trace: + split-repositories: runs-on: ubuntu-latest + strategy: + matrix: + # Structure of the config tuple is: + # 0: Type of package (e.g. open-feature/flagd-*provider*) + # 1: Name of package (sans-org-prefix e.g. open-feature/*flagd*-provider) + # 2: Name of subdirectory (e.g. providers/*Flagd*) + config: + - [hook, dd-trace, DDTrace] + - [hook, otel, OpenTelemetry] + - [hook, validator, Validators] + - [provider, cloudbees, CloudBees] + - [provider, flagd, Flagd] + - [provider, split, Split] + - [provider, go-feature-flag, GoFeatureFlag] steps: + - name: Detect run requirement + id: shouldRun + run: | + input_ref="${{ github.event.release.tag_name }}" + if [ -z "$input_ref" ]; then + input_ref="${{ inputs.tag }}" + fi + result=0 + if [[ "$inputRef" == open-feature/${{ matrix.config[1] }}-${{ matrix.config[0] }}-* ]]; then + result=1 + fi + echo "::set-output name=result::${result}" - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-hook-dd-trace - uses: tcarrio/git-filter-repo-docker-action@v1 + if: ${{ steps.shouldRun.outputs.result == '1' }} + run: | + git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" + cd "$GITHUB_WORKSPACE" + git checkout "$GITHUB_SHA" + - name: Replace string in GitHub Actions + if: ${{ steps.shouldRun.outputs.result == '1' }} + id: targetRef + run: | + input_ref="${{ github.event.release.tag_name }}" + if [ -z "$input_ref" ]; then + input_ref="${{ inputs.tag }}" + fi + if [ -n "$input_ref" ]; then + input_ref="refs/tags/$input_ref" + target_ref="$(echo -n "$input_ref"|sed 's#open-feature/${{ matrix.config[1] }}-${{ matrix.config[0] }}-##')" + fi + echo "::set-output name=result::${target_ref}" + - name: Filter and push package ${{ matrix.config[1] }}-${{ matrix.config[0] }} + if: ${{ steps.shouldRun.outputs.result == '1' }} + uses: tcarrio/git-filter-repo-docker-action@v1.5.0 with: privateKey: ${{ secrets.SSH_PRIVATE_KEY }} targetOrg: open-feature-php - targetRepo: dd-trace-hook - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/DDTrace/ --force' - - split-hook-otel: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-hook-otel - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: otel-hook - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/OpenTelemetry/ --force' - - split-hook-validator: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-hook-validator - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: validators-hook - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter hooks/Validators/ --force' - - split-provider-cloudbees: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-provider-cloudbees - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: cloudbees-provider - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/CloudBees/ --force' - - split-provider-flagd: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-provider-flagd - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: flagd-provider - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/Flagd/ --force' - - split-provider-split: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-provider-split - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: split-provider - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/Split/ --force' - - split-provider-go-feature-flag: - runs-on: ubuntu-latest - steps: - - name: checkout - run: git clone "$GITHUB_SERVER_URL"/"$GITHUB_REPOSITORY" "$GITHUB_WORKSPACE" && cd "$GITHUB_WORKSPACE" && git checkout "$GITHUB_SHA" - - name: push-provider-split - uses: tcarrio/git-filter-repo-docker-action@v1 - with: - privateKey: ${{ secrets.SSH_PRIVATE_KEY }} - targetOrg: open-feature-php - targetRepo: go-feature-flag-provider - targetBranch: refs/tags/${{ github.event.release.tag_name }} - filterArguments: '--subdirectory-filter providers/GoFeatureFlag/ --force' + targetRepo: ${{ matrix.config[1] }}-${{ matrix.config[0] }} + targetBranch: ${{ steps.targetRef.outputs.result }} + tagFilter: ^open-feature/${{ matrix.config[1] }}- + filterArguments: | + --subdirectory-filter "${{matrix.config[0] }}s/${{ matrix.config[2] }}/" \ + --tag-rename "open-feature/${{ matrix.config[1] }}-${{ matrix.config[0] }}-:" \ + --force diff --git a/.gitsplit.yml b/.gitsplit.yml deleted file mode 100644 index ee802707..00000000 --- a/.gitsplit.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Path to a cache directory Used to speed up the split over time by reusing git's objects -cache_url: "/cache/gitsplit" - -# Path to the repository to split (default = current path) -project_url: "https://github.com/open-feature/php-sdk-contrib.git" - -# List of splits. -splits: - - prefix: "hooks/OpenTelemetry" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/otel-hook.git" - - prefix: "hooks/DDTrace" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/dd-trace-hook.git" - - prefix: "hooks/Validators" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/validators-hook.git" - - prefix: "providers/Flagd" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/flagd-provider.git" - - prefix: "providers/Split" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/split-provider.git" - - prefix: "providers/CloudBees" - target: "https://$%7BGH_TOKEN%7D@github.com/open-feature-php/cloudbees-provider.git" - -# List of references to split (defined as regexp) -origins: - - ^main$ - - ^test$ - - ^split$ - - ^v\d+\.\d+\.\d+$ - - ^\d+\.\d+\.\d+$ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c28141e7..39bcb904 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,9 +1,9 @@ { - "hooks/DDTrace": "0.2.0", - "hooks/OpenTelemetry": "0.2.0", - "hooks/Validators": "0.2.0", - "providers/CloudBees": "0.3.0", - "providers/Flagd": "0.4.0", - "providers/Split": "0.3.0", - "providers/GoFeatureFlag": "0.1.0" + "hooks/DDTrace": "1.0.0", + "hooks/OpenTelemetry": "1.0.0", + "hooks/Validators": "1.0.0", + "providers/CloudBees": "1.0.0", + "providers/Flagd": "1.0.0", + "providers/Split": "1.0.0", + "providers/GoFeatureFlag": "1.0.0" } \ No newline at end of file diff --git a/release-please-config.json b/release-please-config.json index 84279a5e..e84fa621 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -8,31 +8,31 @@ "packages": { "hooks/DDTrace": { "package-name": "open-feature/dd-trace-hook", - "release-as": "0.2.0" + "release-as": "1.0.0" }, "hooks/OpenTelemetry": { "package-name": "open-feature/otel-hook", - "release-as": "0.2.0" + "release-as": "1.0.0" }, "hooks/Validators": { "package-name": "open-feature/validators-hook", - "release-as": "0.2.0" + "release-as": "1.0.0" }, "providers/CloudBees": { "package-name": "open-feature/cloudbees-provider", - "release-as": "0.3.0" + "release-as": "1.0.0" }, "providers/Flagd": { "package-name": "open-feature/flagd-provider", - "release-as": "0.4.0" + "release-as": "1.0.0" }, "providers/Split": { "package-name": "open-feature/split-provider", - "release-as": "0.3.0" + "release-as": "1.0.0" }, "providers/GoFeatureFlag": { "package-name": "open-feature/go-feature-flag-provider", - "release-as": "0.1.0" + "release-as": "1.0.0" } } } From 1d2d5f135750e80fc18e933205957529de35e610 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:15:12 -0400 Subject: [PATCH 74/90] chore(main): release open-feature/split-provider 1.0.0 (#89) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- providers/Split/CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/providers/Split/CHANGELOG.md b/providers/Split/CHANGELOG.md index e15d6d64..f9b4b8d2 100644 --- a/providers/Split/CHANGELOG.md +++ b/providers/Split/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/split-provider-v1.0.0...open-feature/split-provider-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* reset release-please config ([#40](https://github.com/open-feature/php-sdk-contrib/issues/40)) +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Bug Fixes + +* declaration for provider name ([#105](https://github.com/open-feature/php-sdk-contrib/issues/105)) ([42919fd](https://github.com/open-feature/php-sdk-contrib/commit/42919fdb8a2d3992ac529ddd7e90d6b99b340732)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) +* reset release-please config ([#40](https://github.com/open-feature/php-sdk-contrib/issues/40)) ([b9a3b7e](https://github.com/open-feature/php-sdk-contrib/commit/b9a3b7e1017dc56ddfdd767fb8dab2d01b641699)) + ## [0.3.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/split-provider-0.3.0...open-feature/split-provider-0.3.0) (2023-02-12) From fcbc9f887e6784d214b05c0584438d564df074e2 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Tue, 3 Sep 2024 23:21:52 -0400 Subject: [PATCH 75/90] fix: input_ref naming smh Signed-off-by: Tom Carrio --- .github/workflows/split_monorepo.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index f51f260f..1bde69a9 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -35,7 +35,7 @@ jobs: input_ref="${{ inputs.tag }}" fi result=0 - if [[ "$inputRef" == open-feature/${{ matrix.config[1] }}-${{ matrix.config[0] }}-* ]]; then + if [[ "$input_ref" == open-feature/${{ matrix.config[1] }}-${{ matrix.config[0] }}-* ]]; then result=1 fi echo "::set-output name=result::${result}" From 3cb56c171e6fb010778b056f475211f4918fbdba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:27:49 -0400 Subject: [PATCH 76/90] chore(main): release open-feature/dd-trace-hook 1.0.0 (#107) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/DDTrace/CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hooks/DDTrace/CHANGELOG.md b/hooks/DDTrace/CHANGELOG.md index 20c703b4..e589e582 100644 --- a/hooks/DDTrace/CHANGELOG.md +++ b/hooks/DDTrace/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/dd-trace-hook-v1.0.0...open-feature/dd-trace-hook-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* fix release-please config ([#38](https://github.com/open-feature/php-sdk-contrib/issues/38)) +* fix release-please config + +### Features + +* dd-trace hook ([#26](https://github.com/open-feature/php-sdk-contrib/issues/26)) ([d2b1a04](https://github.com/open-feature/php-sdk-contrib/commit/d2b1a0440bbb0d1fa557b3aefd32eee6267f2823)) +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) + + +### Miscellaneous Chores + +* fix release-please config ([0210952](https://github.com/open-feature/php-sdk-contrib/commit/0210952af1d6774744c633507a9bec73f3cf7251)) +* fix release-please config ([#38](https://github.com/open-feature/php-sdk-contrib/issues/38)) ([8ee9fe3](https://github.com/open-feature/php-sdk-contrib/commit/8ee9fe37584ad6754272ad3ac016902e6ebd48d8)) + ## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/dd-trace-hook-0.2.0...open-feature/dd-trace-hook-0.2.0) (2024-08-05) From 7c515a17368da22418d5591c70cb2c3755f9ab64 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Tue, 3 Sep 2024 23:28:45 -0400 Subject: [PATCH 77/90] fix: validators not validator Signed-off-by: Tom Carrio --- .github/workflows/split_monorepo.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/split_monorepo.yaml b/.github/workflows/split_monorepo.yaml index 1bde69a9..56230cf5 100644 --- a/.github/workflows/split_monorepo.yaml +++ b/.github/workflows/split_monorepo.yaml @@ -21,7 +21,7 @@ jobs: config: - [hook, dd-trace, DDTrace] - [hook, otel, OpenTelemetry] - - [hook, validator, Validators] + - [hook, validators, Validators] - [provider, cloudbees, CloudBees] - [provider, flagd, Flagd] - [provider, split, Split] From e911ca59e9262593df1b23c7ff443b6eb98d18e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:29:52 -0400 Subject: [PATCH 78/90] chore(main): release open-feature/validators-hook 1.0.0 (#88) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/Validators/CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hooks/Validators/CHANGELOG.md b/hooks/Validators/CHANGELOG.md index 2ccfd5e7..ddb94333 100644 --- a/hooks/Validators/CHANGELOG.md +++ b/hooks/Validators/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/validators-hook-v1.0.0...open-feature/validators-hook-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) +* **validators-hook:** created new package with validation offering ([#30](https://github.com/open-feature/php-sdk-contrib/issues/30)) ([a2501e6](https://github.com/open-feature/php-sdk-contrib/commit/a2501e6440e8f25ce3231fffd225f5cf13ab5fe4)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) + ## [0.2.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/validators-hook-0.2.0...open-feature/validators-hook-0.2.0) (2023-02-12) From d088bd48c4ff9bfd7e02662e7b06676f63904a91 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:31:53 -0400 Subject: [PATCH 79/90] chore(main): release open-feature/go-feature-flag-provider 1.0.0 (#111) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- providers/GoFeatureFlag/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/providers/GoFeatureFlag/CHANGELOG.md b/providers/GoFeatureFlag/CHANGELOG.md index 699fd8f0..ea1f8de0 100644 --- a/providers/GoFeatureFlag/CHANGELOG.md +++ b/providers/GoFeatureFlag/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/go-feature-flag-provider-v1.0.0...open-feature/go-feature-flag-provider-1.0.0) (2024-09-04) + + +### Features + +* new GO Feature Flag PHP provider ([#106](https://github.com/open-feature/php-sdk-contrib/issues/106)) ([4ba0033](https://github.com/open-feature/php-sdk-contrib/commit/4ba0033dd08a2f9f2ab02ebd49b7b6e03d11eb79)) + ## 0.1.0 (2024-09-03) From 430a3e3ff663a000bd0def2d95f792710f7d8588 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:33:42 -0400 Subject: [PATCH 80/90] chore(main): release open-feature/flagd-provider 1.0.0 (#87) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- providers/Flagd/CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/providers/Flagd/CHANGELOG.md b/providers/Flagd/CHANGELOG.md index c6f2bd0a..18bbdc3a 100644 --- a/providers/Flagd/CHANGELOG.md +++ b/providers/Flagd/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/flagd-provider-v1.0.0...open-feature/flagd-provider-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) +* **flagd:** support newer psr/log ([bf6f449](https://github.com/open-feature/php-sdk-contrib/commit/bf6f449ea790c0021698d33ebb59fab576e23341)) +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Bug Fixes + +* declaration for provider name ([#105](https://github.com/open-feature/php-sdk-contrib/issues/105)) ([42919fd](https://github.com/open-feature/php-sdk-contrib/commit/42919fdb8a2d3992ac529ddd7e90d6b99b340732)) +* **deps:** update dependency psr/http-message to v2 ([#72](https://github.com/open-feature/php-sdk-contrib/issues/72)) ([bb18c04](https://github.com/open-feature/php-sdk-contrib/commit/bb18c04af7280c71c013d5a2e11903506b815f8b)) +* flagd documentation ([#83](https://github.com/open-feature/php-sdk-contrib/issues/83)) ([684367c](https://github.com/open-feature/php-sdk-contrib/commit/684367cd14b6b55cded5accdc5b92eb00986404c)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) + ## [0.4.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/flagd-provider-0.4.0...open-feature/flagd-provider-0.4.0) (2023-02-12) From 029134e096620d6728e162e32ce01aef18188698 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:34:32 -0400 Subject: [PATCH 81/90] chore(main): release open-feature/cloudbees-provider 1.0.0 (#86) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- providers/CloudBees/CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/providers/CloudBees/CHANGELOG.md b/providers/CloudBees/CHANGELOG.md index 72863a53..17da82b3 100644 --- a/providers/CloudBees/CHANGELOG.md +++ b/providers/CloudBees/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/cloudbees-provider-v1.0.0...open-feature/cloudbees-provider-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Bug Fixes + +* declaration for provider name ([#105](https://github.com/open-feature/php-sdk-contrib/issues/105)) ([42919fd](https://github.com/open-feature/php-sdk-contrib/commit/42919fdb8a2d3992ac529ddd7e90d6b99b340732)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) + ## 0.3.0 (2023-01-09) From 39d88fbc71274ee6c97918e3f58d91e5f969dbc9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 23:35:34 -0400 Subject: [PATCH 82/90] chore(main): release open-feature/otel-hook 1.0.0 (#85) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- hooks/OpenTelemetry/CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/hooks/OpenTelemetry/CHANGELOG.md b/hooks/OpenTelemetry/CHANGELOG.md index e1664184..46150196 100644 --- a/hooks/OpenTelemetry/CHANGELOG.md +++ b/hooks/OpenTelemetry/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/otel-hook-v1.0.0...open-feature/otel-hook-1.0.0) (2024-09-04) + + +### ⚠ BREAKING CHANGES + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) + +### Features + +* deprecate php 7 ([#59](https://github.com/open-feature/php-sdk-contrib/issues/59)) ([d028e6d](https://github.com/open-feature/php-sdk-contrib/commit/d028e6d7741d07b7edef21b43b249fdb2d18d8f2)) +* otel hook ([#22](https://github.com/open-feature/php-sdk-contrib/issues/22)) ([be3f1e9](https://github.com/open-feature/php-sdk-contrib/commit/be3f1e9ed37dee4bbce8e3701e4693c1b949c398)) +* **otel-hook:** autoload registration of otel hook ([#25](https://github.com/open-feature/php-sdk-contrib/issues/25)) ([789a95c](https://github.com/open-feature/php-sdk-contrib/commit/789a95c47bc278b333bf8b241b0e342baa27acc5)) + + +### Miscellaneous Chores + +* reset release-please ([#39](https://github.com/open-feature/php-sdk-contrib/issues/39)) ([b452080](https://github.com/open-feature/php-sdk-contrib/commit/b452080443d837c66b554b1bb1a07cadba5a152a)) + ## 0.2.0 (2023-01-09) From e542f09873cc1008ff3f2fa2ee8893c352191c3c Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 4 Sep 2024 05:48:39 +0200 Subject: [PATCH 83/90] chore: Add GOFF to readme (#109) Signed-off-by: Thomas Poignant --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 42afa3a0..421d18d3 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ The `php-contrib-sdk` repository is a monorepository containing various provider - [Flagd](./providers/Flagd/README.md) - [Split](./providers/Split/README.md) - [CloudBees](./providers/CloudBees/README.md) + - [GO Feature Flag](./providers/GOFeatureFlag/README.md) - Hooks - [OpenTelemetry](./hooks/OpenTelemetry/README.md) - [Datadog](./hooks/DDTrace/README.md) From 28299f69b2fba8321e8577bbade7e24025b22f20 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 4 Sep 2024 20:44:26 +0200 Subject: [PATCH 84/90] chore: Fixing some link typo (#113) * Update README.md Signed-off-by: Thomas Poignant * Update README.md Signed-off-by: Thomas Poignant --------- Signed-off-by: Thomas Poignant --- README.md | 2 +- providers/GoFeatureFlag/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 421d18d3..f80b3b56 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The `php-contrib-sdk` repository is a monorepository containing various provider - [Flagd](./providers/Flagd/README.md) - [Split](./providers/Split/README.md) - [CloudBees](./providers/CloudBees/README.md) - - [GO Feature Flag](./providers/GOFeatureFlag/README.md) + - [GO Feature Flag](./providers/GoFeatureFlag/README.md) - Hooks - [OpenTelemetry](./hooks/OpenTelemetry/README.md) - [Datadog](./hooks/DDTrace/README.md) diff --git a/providers/GoFeatureFlag/README.md b/providers/GoFeatureFlag/README.md index 13295546..c81a1706 100644 --- a/providers/GoFeatureFlag/README.md +++ b/providers/GoFeatureFlag/README.md @@ -5,8 +5,8 @@ # GO Feature Flag - OpenFeature PHP provider

- - + + Packagist Version Documentation Issues From 1c2352941d0346bc62a9ac4742395b3d3276d26f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:15:24 -0500 Subject: [PATCH 85/90] chore(deps): update dependency datadog/dd-trace to ^0.99.0 (#56) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- hooks/DDTrace/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/DDTrace/composer.json b/hooks/DDTrace/composer.json index a385e0e2..dd6eae71 100644 --- a/hooks/DDTrace/composer.json +++ b/hooks/DDTrace/composer.json @@ -27,7 +27,7 @@ "open-feature/sdk": "^2.0" }, "require-dev": { - "datadog/dd-trace": "^0.82.0", + "datadog/dd-trace": "^0.99.0", "ergebnis/composer-normalize": "^2.25", "friendsofphp/php-cs-fixer": "^3.13", "hamcrest/hamcrest-php": "^2.0", From e3aef1ad277d8fe90d3f4ab6ddb3e509dafb45f8 Mon Sep 17 00:00:00 2001 From: CristianCurteanu Date: Wed, 22 Jan 2025 17:33:09 +0200 Subject: [PATCH 86/90] feat: upgrade rollout/rox to 6.0.1 (#119) Signed-off-by: CristianCurteanu --- providers/CloudBees/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/CloudBees/composer.json b/providers/CloudBees/composer.json index 67640d8a..c4946acc 100644 --- a/providers/CloudBees/composer.json +++ b/providers/CloudBees/composer.json @@ -25,7 +25,7 @@ "require": { "php": "^8", "open-feature/sdk": "^2.0", - "rollout/rox": "^5.0" + "rollout/rox": "^6.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.25", From 362a36ad38036e959283ea8a967ff73a36fc1f7a Mon Sep 17 00:00:00 2001 From: Michael Beemer Date: Fri, 24 Jan 2025 13:02:53 -0500 Subject: [PATCH 87/90] chore: remove hardcoded version (#122) Signed-off-by: Michael Beemer --- release-please-config.json | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index e84fa621..c25cd034 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -7,32 +7,25 @@ "include-v-in-tag": false, "packages": { "hooks/DDTrace": { - "package-name": "open-feature/dd-trace-hook", - "release-as": "1.0.0" + "package-name": "open-feature/dd-trace-hook" }, "hooks/OpenTelemetry": { - "package-name": "open-feature/otel-hook", - "release-as": "1.0.0" + "package-name": "open-feature/otel-hook" }, "hooks/Validators": { - "package-name": "open-feature/validators-hook", - "release-as": "1.0.0" + "package-name": "open-feature/validators-hook" }, "providers/CloudBees": { - "package-name": "open-feature/cloudbees-provider", - "release-as": "1.0.0" + "package-name": "open-feature/cloudbees-provider" }, "providers/Flagd": { - "package-name": "open-feature/flagd-provider", - "release-as": "1.0.0" + "package-name": "open-feature/flagd-provider" }, "providers/Split": { - "package-name": "open-feature/split-provider", - "release-as": "1.0.0" + "package-name": "open-feature/split-provider" }, "providers/GoFeatureFlag": { - "package-name": "open-feature/go-feature-flag-provider", - "release-as": "1.0.0" + "package-name": "open-feature/go-feature-flag-provider" } } } From c9ffd9fb4a9b26db01d72cbda8fe90260d3b8fc1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:04:11 -0500 Subject: [PATCH 88/90] chore(main): release open-feature/cloudbees-provider 1.1.0 (#121) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- providers/CloudBees/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 39bcb904..664c1957 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -2,7 +2,7 @@ "hooks/DDTrace": "1.0.0", "hooks/OpenTelemetry": "1.0.0", "hooks/Validators": "1.0.0", - "providers/CloudBees": "1.0.0", + "providers/CloudBees": "1.1.0", "providers/Flagd": "1.0.0", "providers/Split": "1.0.0", "providers/GoFeatureFlag": "1.0.0" diff --git a/providers/CloudBees/CHANGELOG.md b/providers/CloudBees/CHANGELOG.md index 17da82b3..a613ef92 100644 --- a/providers/CloudBees/CHANGELOG.md +++ b/providers/CloudBees/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.1.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/cloudbees-provider-1.0.0...open-feature/cloudbees-provider-1.1.0) (2025-01-24) + + +### Features + +* upgrade rollout/rox to 6.0.1 ([#119](https://github.com/open-feature/php-sdk-contrib/issues/119)) ([e3aef1a](https://github.com/open-feature/php-sdk-contrib/commit/e3aef1ad277d8fe90d3f4ab6ddb3e509dafb45f8)) + ## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/cloudbees-provider-v1.0.0...open-feature/cloudbees-provider-1.0.0) (2024-09-04) From 5dfcfbb9f16555585ab8bbe6ede1bdf1d177ea76 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Wed, 29 Jan 2025 10:16:04 +0100 Subject: [PATCH 89/90] feat(go-feature-flag): Support exporter metadata (#120) * chore(deps): update dependency datadog/dd-trace to ^0.99.0 (#56) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: Thomas Poignant * feat(go-feature-flag): Support exporter metadata Signed-off-by: Thomas Poignant * upgrade rollout/rox to 6.0.1 (#119) Signed-off-by: CristianCurteanu Signed-off-by: Thomas Poignant * fix php doc Signed-off-by: Thomas Poignant * chore: remove hardcoded version (#122) Signed-off-by: Michael Beemer Signed-off-by: Thomas Poignant * fix: add explicit usage of json_decode Signed-off-by: Thomas Poignant * fix: use in alphabetical order Signed-off-by: Thomas Poignant * fix lint type in doc Signed-off-by: Thomas Poignant --------- Signed-off-by: Thomas Poignant Signed-off-by: CristianCurteanu Signed-off-by: Michael Beemer Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: CristianCurteanu Co-authored-by: Michael Beemer --- providers/GoFeatureFlag/src/config/Config.php | 33 ++++++++++++- .../GoFeatureFlag/src/controller/OfrepApi.php | 3 ++ .../tests/unit/GoFeatureFlagProviderTest.php | 47 +++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/providers/GoFeatureFlag/src/config/Config.php b/providers/GoFeatureFlag/src/config/Config.php index 510bc9e1..8ba5851f 100644 --- a/providers/GoFeatureFlag/src/config/Config.php +++ b/providers/GoFeatureFlag/src/config/Config.php @@ -19,17 +19,38 @@ class Config */ private ?ClientInterface $httpclient; + /** + * @var array exporterMetadata - is the metadata we send to the GO Feature Flag relay proxy when we report + * the evaluation data usage. + * + * ‼️Important: If you are using a GO Feature Flag relay proxy before version v1.41.0, the information of this + * field will not be added to your feature events. + */ + private array $exporterMetadata = []; + /** * @param string $endpoint - The endpoint to your GO Feature Flag Instance * @param string|null $apiKey - API Key to use to connect to GO Feature Flag * @param array|null $customHeaders - Custom headers you want to send + * @param array|null $exporterMetadata - Metadata to send to the relay proxy during evaluation data collection * @param ClientInterface|null $httpclient - The HTTP Client to use (if you want to use a custom one) */ - public function __construct(string $endpoint, ?string $apiKey = '', ?array $customHeaders = [], ?ClientInterface $httpclient = null) - { + public function __construct( + string $endpoint, + ?string $apiKey = '', + ?array $customHeaders = [], + ?array $exporterMetadata = [], + ?ClientInterface $httpclient = null, + ) { $this->httpclient = $httpclient; $this->endpoint = $endpoint; $this->customHeaders = $customHeaders ?? []; + + // set default exporter metadata fields + $this->exporterMetadata = $exporterMetadata ?? []; + $this->exporterMetadata['openfeature'] = true; + $this->exporterMetadata['provider'] = 'php'; + if ($apiKey !== null && $apiKey !== '') { $this->customHeaders['Authorization'] = 'Bearer ' . $apiKey; } @@ -57,4 +78,12 @@ public function getHttpClient(): ?ClientInterface { return $this->httpclient; } + + /** + * @return array + */ + public function getExporterMetadata(): array + { + return $this->exporterMetadata; + } } diff --git a/providers/GoFeatureFlag/src/controller/OfrepApi.php b/providers/GoFeatureFlag/src/controller/OfrepApi.php index d5d17edb..1b0f1700 100644 --- a/providers/GoFeatureFlag/src/controller/OfrepApi.php +++ b/providers/GoFeatureFlag/src/controller/OfrepApi.php @@ -75,6 +75,9 @@ public function evaluate(string $flagKey, EvaluationContext $evaluationContext): ['targetingKey' => $evaluationContext->getTargetingKey()], ); + // Add exporter metadata to the context + $fields['gofeatureflag'] = ['exporterMetadata' => $this->options->getExporterMetadata()]; + $requestBody = json_encode(['context' => $fields]); if ($requestBody === false) { throw new ParseException('failed to encode request body'); diff --git a/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php b/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php index e990ec90..2f1b0a68 100644 --- a/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php +++ b/providers/GoFeatureFlag/tests/unit/GoFeatureFlagProviderTest.php @@ -21,6 +21,7 @@ use ReflectionException; use function PHPUnit\Framework\assertEquals; +use function json_decode; use function json_encode; class GoFeatureFlagProviderTest extends TestCase @@ -474,6 +475,52 @@ public function testReturnAnErrorAPIResponseIf500(): void assertEquals('boolean_flag', $got->getFlagKey()); } + public function testShouldSendExporterMetadataInContext(): void + { + $mockClient = $this->createMock(ClientInterface::class); + $mockResponse = new Response(200, [], json_encode([ + 'key' => 'integer_key', + 'value' => 42, + 'reason' => 'TARGETING_MATCH', + 'variant' => 'default', + ])); + + $requestBody = ''; + $mockClient + ->expects($this->once()) + ->method('sendRequest') + ->willReturnCallback(function ($request) use ($mockResponse, &$requestBody) { + $requestBody = $request->getBody()->getContents(); + + return $mockResponse; + }); + + $config = new Config( + 'http://gofeatureflag.org/', + null, + [], + ['key1' => 'value', 'key2' => 123, 'key3' => 123.45], + ); + + $provider = new GoFeatureFlagProvider($config); + $this->mockHttpClient($provider, $mockClient); + + $api = OpenFeatureAPI::getInstance(); + $api->setProvider($provider); + $client = $api->getClient(); + $client->getBooleanDetails('boolean_flag', false, $this->defaultEvaluationContext); + + // get the request body of the request received by the mock client + $want = ['key1' => 'value', + 'key2' => 123, + 'key3' => 123.45, + 'openfeature' => true, + 'provider' => 'php', + ]; + $got = json_decode($requestBody, true)['context']['gofeatureflag']['exporterMetadata']; + assertEquals($want, $got); + } + protected function setUp(): void { parent::setUp(); From 030052b31d189e086ccb81b374bbeb24bb8a58f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:28:52 +0100 Subject: [PATCH 90/90] chore(main): release open-feature/go-feature-flag-provider 1.1.0 (#124) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- providers/GoFeatureFlag/CHANGELOG.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 664c1957..b02e2c18 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -5,5 +5,5 @@ "providers/CloudBees": "1.1.0", "providers/Flagd": "1.0.0", "providers/Split": "1.0.0", - "providers/GoFeatureFlag": "1.0.0" + "providers/GoFeatureFlag": "1.1.0" } \ No newline at end of file diff --git a/providers/GoFeatureFlag/CHANGELOG.md b/providers/GoFeatureFlag/CHANGELOG.md index ea1f8de0..53ba5145 100644 --- a/providers/GoFeatureFlag/CHANGELOG.md +++ b/providers/GoFeatureFlag/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.1.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/go-feature-flag-provider-1.0.0...open-feature/go-feature-flag-provider-1.1.0) (2025-01-29) + + +### Features + +* **go-feature-flag:** Support exporter metadata ([#120](https://github.com/open-feature/php-sdk-contrib/issues/120)) ([5dfcfbb](https://github.com/open-feature/php-sdk-contrib/commit/5dfcfbb9f16555585ab8bbe6ede1bdf1d177ea76)) + ## [1.0.0](https://github.com/open-feature/php-sdk-contrib/compare/open-feature/go-feature-flag-provider-v1.0.0...open-feature/go-feature-flag-provider-1.0.0) (2024-09-04)