From 8a87607dfc9f63010b5aa6a0772a72d76c11d1db Mon Sep 17 00:00:00 2001 From: Evandro Myller Date: Thu, 29 Oct 2026 17:16:23 -0300 Subject: [PATCH] feat(CI): Set up CodSpeed Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/codspeed.yml | 43 +++++++++++ .gitmodules | 4 + Makefile | 12 +++ benchmarks/SdkBenchmark.php | 103 +++++++++++++++++++++++++ benchmarks/run.php | 29 +++++++ codspeed.yml | 33 ++++++++ composer.json | 5 ++ tests/Engine/EngineTests/SdkBenchmarks | 1 + 8 files changed, 230 insertions(+) create mode 100644 .github/workflows/codspeed.yml create mode 100644 Makefile create mode 100644 benchmarks/SdkBenchmark.php create mode 100644 benchmarks/run.php create mode 100644 codspeed.yml create mode 160000 tests/Engine/EngineTests/SdkBenchmarks diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml new file mode 100644 index 0000000..d27868e --- /dev/null +++ b/.github/workflows/codspeed.yml @@ -0,0 +1,43 @@ +name: CodSpeed + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: + contents: read # Check out the repository and its submodules + id-token: write # Authenticate result uploads to CodSpeed via OIDC + +jobs: + benchmarks: + name: Run benchmarks + runs-on: codspeed-macro + + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + submodules: recursive + persist-credentials: false + + - name: Set up PHP + uses: shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # 2.40.0 + with: + php-version: "8.5" + extensions: "bcmath, gmp" + + - name: Install CodSpeed CLI + env: + CODSPEED_VERSION: 5.6.0 + CODSPEED_INSTALLER_SHA256: bf1bf63661e203bcabc0c84fdef0337f8658fc8340c467a6a3bca81040d99f40 + run: | + installer=$(mktemp) + curl -fsSL -o "$installer" "https://codspeed.io/v$CODSPEED_VERSION/install.sh" + echo "$CODSPEED_INSTALLER_SHA256 $installer" | sha256sum --check --strict + bash "$installer" --quiet + + - name: Run benchmarks + run: make benchmark diff --git a/.gitmodules b/.gitmodules index a55a027..47f5132 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,7 @@ path = tests/Engine/EngineTests/EngineTestData url = git@github.com:Flagsmith/engine-test-data.git branch = v3.7.0 +[submodule "tests/Engine/EngineTests/SdkBenchmarks"] + path = tests/Engine/EngineTests/SdkBenchmarks + url = https://github.com/Flagsmith/sdk-benchmarks.git + branch = 0.0.2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b49e11 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +SDK_BENCHMARKS := tests/Engine/EngineTests/SdkBenchmarks + +$(SDK_BENCHMARKS)/environments: + git submodule update --init -- $(SDK_BENCHMARKS) + +vendor/autoload.php: composer.json + composer install --prefer-dist --no-interaction + touch $@ + +.PHONY: benchmark +benchmark: vendor/autoload.php $(SDK_BENCHMARKS)/environments + SDK_BENCHMARKS_ENVIRONMENTS_DIR=$(abspath $(SDK_BENCHMARKS)/environments) codspeed run --mode walltime diff --git a/benchmarks/SdkBenchmark.php b/benchmarks/SdkBenchmark.php new file mode 100644 index 0000000..2fa4282 --- /dev/null +++ b/benchmarks/SdkBenchmark.php @@ -0,0 +1,103 @@ + 'plan-7', + 'age' => 30, + 'country' => 'GB', + 'version' => '2.5.1', + 'email' => 'jane@example.com', + 'user_id' => 12, + 'beta' => true, + 'score' => 95, + 'tier' => 'pro', + 'device' => 'iPhone 15', + ]; + + private Flagsmith $client; + + /** + * Build a locally evaluating client serving the environment document from memory. + */ + public function __construct(string $environmentsDir, string $environment) + { + $environmentDocument = file_get_contents("{$environmentsDir}/{$environment}.json"); + + $this->client = (new Flagsmith( + apiKey: 'ser.benchmark', + host: 'http://flagsmith.benchmark/api/v1/', + environmentTtl: 86400, // Refreshed by benchmarks only + ))->withClient(new Client([ + 'handler' => static fn (RequestInterface $request): PromiseInterface => Create::promiseFor( + new Response(200, ['Content-Type' => 'application/json'], $environmentDocument), + ), + ])); + $this->client->updateEnvironment(); + } + + /** + * Get a feature value from the environment flags. + */ + public function getEnvironmentFlags(): mixed + { + return $this->client->getEnvironmentFlags()->getFeatureValue('feature_1'); + } + + /** + * Check a feature for an identity with identity overrides. + */ + public function getIdentityFlagsWithIdentityOverrides(): bool + { + return $this->client->getIdentityFlags(self::IDENTITY_OVERRIDES_IDENTIFIER)->isFeatureEnabled('feature_8'); + } + + /** + * Get a feature value for an identity without traits. + */ + public function getIdentityFlagsNoTraits(): mixed + { + return $this->client->getIdentityFlags(self::IDENTIFIER)->getFeatureValue('feature_1'); + } + + /** + * Get a feature value for an identity with traits. + */ + public function getIdentityFlagsWithTraits(): mixed + { + return $this->client->getIdentityFlags(self::IDENTIFIER, (object) self::TRAITS)->getFeatureValue('feature_1'); + } + + /** + * List the segments of an identity with traits. + * @return array + */ + public function getIdentitySegmentsWithTraits(): array + { + return $this->client->getIdentitySegments(self::IDENTIFIER, (object) self::TRAITS); + } +} diff --git a/benchmarks/run.php b/benchmarks/run.php new file mode 100644 index 0000000..54571b1 --- /dev/null +++ b/benchmarks/run.php @@ -0,0 +1,29 @@ + php %s <%s> <%s>\n", + $argv[0], + implode('|', SdkBenchmark::BENCHMARKS), + implode('|', SdkBenchmark::ENVIRONMENTS), + )); + exit(2); +} + +$sdkBenchmark = new SdkBenchmark($environmentsDir, $environment); +for ($revolution = 0; $revolution < REVOLUTIONS; $revolution++) { + $sdkBenchmark->$benchmark(); +} diff --git a/codspeed.yml b/codspeed.yml new file mode 100644 index 0000000..3929ce2 --- /dev/null +++ b/codspeed.yml @@ -0,0 +1,33 @@ +$schema: https://raw.githubusercontent.com/CodSpeedHQ/codspeed/refs/heads/main/schemas/codspeed.schema.json + +benchmarks: + - name: getEnvironmentFlags[small] + exec: php benchmarks/run.php getEnvironmentFlags small + - name: getEnvironmentFlags[medium] + exec: php benchmarks/run.php getEnvironmentFlags medium + - name: getEnvironmentFlags[large] + exec: php benchmarks/run.php getEnvironmentFlags large + - name: getIdentityFlagsWithIdentityOverrides[small] + exec: php benchmarks/run.php getIdentityFlagsWithIdentityOverrides small + - name: getIdentityFlagsWithIdentityOverrides[medium] + exec: php benchmarks/run.php getIdentityFlagsWithIdentityOverrides medium + - name: getIdentityFlagsWithIdentityOverrides[large] + exec: php benchmarks/run.php getIdentityFlagsWithIdentityOverrides large + - name: getIdentityFlagsNoTraits[small] + exec: php benchmarks/run.php getIdentityFlagsNoTraits small + - name: getIdentityFlagsNoTraits[medium] + exec: php benchmarks/run.php getIdentityFlagsNoTraits medium + - name: getIdentityFlagsNoTraits[large] + exec: php benchmarks/run.php getIdentityFlagsNoTraits large + - name: getIdentityFlagsWithTraits[small] + exec: php benchmarks/run.php getIdentityFlagsWithTraits small + - name: getIdentityFlagsWithTraits[medium] + exec: php benchmarks/run.php getIdentityFlagsWithTraits medium + - name: getIdentityFlagsWithTraits[large] + exec: php benchmarks/run.php getIdentityFlagsWithTraits large + - name: getIdentitySegmentsWithTraits[small] + exec: php benchmarks/run.php getIdentitySegmentsWithTraits small + - name: getIdentitySegmentsWithTraits[medium] + exec: php benchmarks/run.php getIdentitySegmentsWithTraits medium + - name: getIdentitySegmentsWithTraits[large] + exec: php benchmarks/run.php getIdentitySegmentsWithTraits large diff --git a/composer.json b/composer.json index ebdfe1f..6b547cb 100644 --- a/composer.json +++ b/composer.json @@ -35,6 +35,11 @@ "FlagsmithTest\\": "tests" } }, + "autoload-dev": { + "psr-4": { + "FlagsmithBenchmark\\": "benchmarks" + } + }, "config": { "allow-plugins": { "php-http/discovery": true diff --git a/tests/Engine/EngineTests/SdkBenchmarks b/tests/Engine/EngineTests/SdkBenchmarks new file mode 160000 index 0000000..7da2be4 --- /dev/null +++ b/tests/Engine/EngineTests/SdkBenchmarks @@ -0,0 +1 @@ +Subproject commit 7da2be42ec7c58a597892e41141d531bd1dd100c