Skip to content

feat: FlagsmithProvider #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

ChrisLightfootWild
Copy link

@ChrisLightfootWild ChrisLightfootWild commented Mar 31, 2025

This PR

  • adds new package, open-feature/flagsmith-provider
    • implements OpenFeature\interfaces\provider\Provider interface for Flagsmith
    • depends on flagsmith/flagsmith-php-client

Notes

image

Follow-up Tasks

How to test

$flagsmith = new Flagsmith\Flagsmith('YOUR_FLAGSMITH_API_KEY');

OpenFeatureAPI::setProvider(new FlagsmithProvider($flagsmith));

Run the tests with:

composer run dev:test

You should (hopefully) see the below output:
image

Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
…coded JSON array

Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
…faultValue

Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
@ChrisLightfootWild ChrisLightfootWild changed the title (feat): FlagsmithProvider feat: FlagsmithProvider Mar 31, 2025
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
@ChrisLightfootWild ChrisLightfootWild marked this pull request as ready for review March 31, 2025 23:55
@ChrisLightfootWild ChrisLightfootWild requested a review from a team as a code owner March 31, 2025 23:55
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to detect if a flag isn't found?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, the Flagsmith client throws a generic FlagsmithClientError in this situation, but I don't see any reason not to use this opportunity to improve the Flagsmith SDK too and extend that exception for a specific FlagsmithFlagNotFound error, similar to how we do it in the python client here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, so this could be implemented once the underlying SDK supports the feature 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, the Flagsmith client throws a generic FlagsmithClientError in this situation, but I don't see any reason not to use this opportunity to improve the Flagsmith SDK too and extend that exception for a specific FlagsmithFlagNotFound error, similar to how we do it in the python client here.

Comment on lines +112 to +117
if ($flag->getEnabled()) {
/** @var array<array-key, mixed>|bool|DateTime|float|int|string|null $value */
$value = $flag->getValue();

$builder->withValue($value);
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other providers (e.g. this logic in the python client) we only check this value before returning the value based on a configuration argument passed to the initialisation of the provider.

I'm not against handling this differently here, but just though I'd highlight it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewelwell should that be a concern of the Flagsmith SDK? If an integrator was using the SDK directly, should they also replicate that logic?

Not against changing it, just trying to clarify for my own understanding.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think my point here is that we're implicitly adding that logic to the provider without a way to change it, right? If someone wants to define a flag in flagsmith to have a value, but remain disabled then there is no way for them to retrieve that value using this implementation of the OpenFeature provider.

In fairness, it's probably not a massive use case, and can be changed in the future if needed, so it's not an important point. I think I'm mostly just posing the question to maintain consistency across our providers, but it's not a hill I'm willing to die on, so if you disagree then I'll go ahead and approve with this behaviour (notwithstanding the other comments).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewelwell I will defer to your expertise here, I was just wanting to better understand some of the rationale.

I'm going to align with the python provider now, thanks.

Comment on lines +55 to +68
public function resolveStringValue(string $flagKey, string $defaultValue, ?EvaluationContext $context = null): ResolutionDetails
{
return $this->resolve($flagKey, $defaultValue, $context);
}

public function resolveIntegerValue(string $flagKey, int $defaultValue, ?EvaluationContext $context = null): ResolutionDetails
{
return $this->resolve($flagKey, $defaultValue, $context);
}

public function resolveFloatValue(string $flagKey, float $defaultValue, ?EvaluationContext $context = null): ResolutionDetails
{
return $this->resolve($flagKey, $defaultValue, $context);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the value from the flagsmith SDK can have different types, shouldn't we do some string casting here (or in the resolve method perhaps?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I will investigate this further.

ChrisLightfootWild and others added 4 commits April 22, 2025 05:41
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Signed-off-by: Chris Lightfoot-Wild <github-clw@wild.me.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants