Git Product home page Git Product logo

flagception-bundle's Introduction

Flagception

Feature toggle bundle on steroids! Flagception is a simple and powerful feature toggle system for php. This bundle integrates the Flagception PHP Libary for symfony 2.7 to 5.* (and php 5.6 to php7.*).

Latest Stable Version Coverage Status Build Status Total Downloads License

SensioLabsInsight

Bundle Version (Tag) Support Symfony Branch
<=3 2.7 - 4.4 3.x
>=4 4.4 - current master
$ composer require flagception/flagception-bundle

Documentation

Quick example

Set some feature in your config (or use your own activator for fetching features from wherever you want) ...

flagception:

    # Your Features (optional you left it empty)
    features:
    
        # Feature name as key
        feature_123:
            # Default flag if inactive or active (default: false)
            default: true
            
        # Feature state from an environment variable
        feature_abc:
            env: FEATURE_ENV_ABC
            
        # Feature with constraint (active if user id is 12 OR it is between 8 am and 6 pm)
        feature_def:
            constraint: 'user_id == 12 or (date("H") > 8 and date("H") < 18)'
                    
        # All togther (chain)
        feature_def:
            default: false
            env: FEATURE_ENV_ABC
            constraint: 'user_id == 12 or (date("H") > 8 and date("H") < 18)'

... and use it in controller, services or twig:

{% if feature('feature_123') %}
    {# Execute if feature is active ... #}
{% endif %}

See usage documentation for detailed examples.

Profiler

This bundle ships a profiler tab, where you can see how often a feature was requested, which results it returns (active or inactive) and the given context.

Image of Profiler

Credits

Profiler icon from https://github.com/ionic-team/ionicons

flagception-bundle's People

Contributors

0x346e3730 avatar ajgarlag avatar amacrobert-meq avatar chq81 avatar haehnchen avatar hanish-singla avatar migo315 avatar mknoop avatar redactedprofile avatar teiling88 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flagception-bundle's Issues

Symfony 6.0 support

Flagception does not list compatibility with Symfony 6.0.

I'm not seeing any deprecation messages when running flagception-bundle 4.1 on Symfony 5.4, so it probably doesn't need any code changes -- just a composer tweak.

This is the error I get when trying to update to Symfony 6.0 in a project that uses flagception-bundle:

$ composer update
Loading composer repositories with package information
Restricting packages listed in "symfony/symfony" to "6.0.*"
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires flagception/flagception-bundle ^4.1 -> satisfiable by flagception/flagception-bundle[4.1.0].
    - flagception/flagception-bundle 4.1.0 requires symfony/dependency-injection ^4.4 | ^5.0 -> found symfony/dependency-injection[v4.4.0-BETA1, ..., v4.4.34, v5.0.0-BETA1, ..., v5.4.0] but these were not loaded, likely because it conflicts with another require.

Implement support for router metadata

In additional to #4 support also routing metadata. They are less costly

/**
 * @Route("foobar", defaults={"_feature": "FOOBAR"})
 */
    public function onKernelController(FilterControllerEvent $event)
    {
        if (!$event->getRequest()->attributes->has('_feature')) {
            return;
        }

        $access = $event->getRequest()->attributes->get('_feature');

        // exit
    }

Cookie feature name

Currently, you enable or disable a feature by cookie with the feature name:

In this configuration, the cookie must contain "feature_123".

# config.yml
flagception:
    features:      
    
        # Activatable via cookie
        feature_123:
            cookie: true

It should be possible to specify an alternative name for the feature in the cookie:

# config.yml
flagception:
    features:      
    
        # Activatable via cookie
        feature_123:
            cookie: MY_SECRET_COOKIE_NAME

This new config allow instead of "true / false" a string with a name, which is then expected as cookie content. If you continue to pass only "true", as before, the feature name is taken.

Support PHP8 Attributes

All the cool kids are using attributes instead of annotations...

I'll submit a PR in a bit, so we can do:

    #[Feature(name: "abc")]
    #[Route('/demo', name: 'app_demo')]
    public function demo(): Response
    {
        return $this->render('app/index.html.twig', [
        ]);
    }

Rename Stash

Rename Stash (eg. StashInterface) to Repository (eg. RepositoryInterface).

@Haehnchen
Do you agree with this name or has another suggestion?

Missing Travis Test for Symfony 5

Currently, we cannot add an Travis test for Symfony 5. The "contentful" Activator requires the Contentful SDK, which does not support Symfony 5 at the moment.

We should find a clean solution for that.

contentful/contentful 1.0.0 requires symfony/console ~2.7|~3.0

[Feature Request] Priority customization

There is currently no way (or none that the docs shows) to to prioritize cookies over anything else. This stop from debugging when having the feature toggled off and enabling it with cookies.

Invoke Controllers

Annotations currently doesn't work with __invoke controllers / actions.

[Refactor] Cookie Activator

The new Flagception Bundle 4.0 will work without the shared "features" tree. Each activator has his own feature tree (if needed) or work without them.

The new "CookieActivator" will replace the old one. It designed to work without a feature list. So all features in your cookie will be enabled:

# config.yml

flagception:   
    activators:    
        cookie:
            enable: true
        database:
            // ...
        contentful:
            // ...
        memory:
            // ...

But you can optionally set a blacklist or whitelist:

# config.yml

flagception:   
    activators:    
        cookie:
            enable: true
            mode: 'blacklist' # (or 'whitelist')
            features:
                 - 'feature_foo'
                 - 'feature_newletter_(.*)' # Can be a regex too 
        database:
            // ...
        contentful:
            // ...
        memory:
            // ...

Symfony profiler doesn't show configured features

Hello,

We're running quite old Symfony 2.8.x based application.
The symfony profiles shows "Features" section but not the configured features. However, I can actually work with them in the code.

Configuration in config.php:

$container->loadFromExtension('flagception', [
    'features' => [
        'feature_123' => [
            'default' => true,
        ],
        
        'feature_abc' => [
            'default' => false,
        ],
    ],
]);

--> can access feature manager, e.g. from a view with:
$this->container->get('flagception.manager.feature_manager')->isActive('feature_123')

Any idea?

Debug container output:

# ./app/console debug:container --env=dev | grep -i flagception
  flagception.activator.array_activator                                                                  Flagception\Activator\ArrayActivator
  flagception.activator.constraint_activator                                                             Flagception\Activator\ConstraintActivator
  flagception.activator.environment_activator                                                            Flagception\Activator\EnvironmentActivator
  flagception.configurator.array_configurator                                                            Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\ArrayConfigurator
  flagception.configurator.constraint_configurator                                                       Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\ConstraintConfigurator
  flagception.configurator.contentful_configurator                                                       Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\ContentfulConfigurator
  flagception.configurator.cookie_configurator                                                           Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\CookieConfigurator
  flagception.configurator.database_configurator                                                         Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\DatabaseConfigurator
  flagception.configurator.environment_configurator                                                      Flagception\Bundle\FlagceptionBundle\DependencyInjection\Configurator\EnvironmentConfigurator
  flagception.listener.routing_metadata_subscriber                                                       Flagception\Bundle\FlagceptionBundle\Listener\RoutingMetadataSubscriber
  flagception.manager.feature_manager                                                                    Flagception\Manager\FeatureManager
  flagception\manager\featuremanagerinterface                                                            alias for "flagception.manager.feature_manager"

TreeBuilder deprecation

Fix TreeBuilder deprecation for Symfony 4.2:

A tree builder without a root node is deprecated since Symfony 4.2 and will not be supported anymore in 5.0.

Merge cookie with config stash

So you can separate which feature are active for cookies. Example:

best_it_feature_toggle:
    features:      
        feature_123:
            active: true
            cookie: false // Default value - disallow this feature for cookie handling
            
        feature_abc:
            active: false
            cookie: true // Allow this feature for cookie handling

[Add] Memory activator

For some it is confusing that some activators (eg cookie, environment) share the "features" tree while others (eg database, contentful) are independent of it.

Therefore, it makes sense to pack the activators that share the same config together. Example:

# config.yml

flagception:   
    features: // moved under "memory"

    activators:    
        memory:
            enable: true
            strategy: all
            features:
                feature_foobar:
                    roles: USER_ROLE
                    cookie: true
                    strategy: all
                feature_bazz:
                    default: true
        database:
            // ...
        contentful:
            // ...
        prismic:
            // ...

The new MemoryActivator is an additional activator to prevent a BC. But in the long term, it should replace the old ArrayActivator, EnvironmentActivator, ConstraintActivator, and CookieActivator.

Merge fields

Just an idea: Merge all fields into one.

Old:

default: false
env: FEATURE_ENV_ABC
constraint: 'user_id == 12 or (date("H") > 8 and date("H") < 18)'

New:

# For default
active: false

# For env
active: 'env(FEATURE_ENV_ABC)'

# For constraint
active: 'user_id == 12 or (date("H") > 8 and date("H") < 18)'

Update Symfony and PHP requirements

Flagception Bundle 3.x supports symfony from 2.7.x and PHP 5.6. The refactored bundle 4.0 should update the requirement and starts with Symfony 4.0 and PHP 7.1.

There should be a 3.2-master Branch for bugfixes.

[Refactor] Environment Activator

The new Flagception Bundle 4.0 will work without the shared "features" tree. Each activator has his own feature tree (if needed) or work without them.

The new "EnvironmentActivator" will replace the old one. It designed to work without a feature list. So all features which are defined as environment variables will be used. You do not have to set it in your config.yml:

# config.yml

flagception:   
    activators:    
        environment:
            enable: true
        database:
            // ...
        contentful:
            // ...
        memory:
            // ...

But you can optionally set a blacklist or whitelist:

# config.yml

flagception:   
    activators:    
        environment:
            enable: true
            mode: 'blacklist' # (or 'whitelist')
            features:
                 - 'feature_foo'
                 - 'feature_newletter_(.*)' # Can be a regex too 
        database:
            // ...
        contentful:
            // ...
        memory:
            // ...

Use sdk cookie activator

Currently this bundle has it own cookie activator. Replace it with the new cookie activator from flagception sdk, which handles cookies in the same way.

is there a way to list the features?

Hi,
We are use to manage our product features with your bundle. Normally we can check if a feature is available on php, twig and Javascript time.

Our main problem is that we want to know the list of the features in twig time. We can create an extension but your bundle encapsulate very well the features array.

Thanks

Flagception\Bundle\FlagceptionBundle\Profiler\FeatureDataCollector::collect declaration error in Symfony5

Compile Error: Declaration of Flagception\Bundle\FlagceptionBundle\Profiler\FeatureDataCollector::collect(Symfony\Component\HttpFoundation\Request $request, Symfony\Component\HttpFoundation\Response $response, ?Exception $exception = NULL) must be compatible with Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface::collect(Symfony\Component\HttpFoundation\Request $request, Symfony\Component\HttpFoundation\Response $response, ?Throwable $exception = NULL)

Activator based on environment values?

The Environment activator does a lookup if a specific environment variable exists. It would be useful to allow a comparison for this environment value.

Use case: I want to enable a feature in dev and preproduction, but not in prod environment.

Do i have to create a custom activator?

Add PHP7.3 for travis

Add PHP7.3 for testing with travis (maybe fix code if necessary). Update README.md for current supported php Versions.

Deprecation notice with Symfony 4.4

When using the bundle in a Symfony 4.4 application this deprecation notice appears:

Using short factory syntax for service "flagception.expression_language" is deprecated since Symfony 4.4, use "['@flagception.factory.expression_language_factory', 'create']" instead.

Support for Symfony 4

Do you have any plans for Symfony 4. I can see few depreciation in this bundle and can contribute towards it.

Provide test helpers for FeatureManager implementation

Prevent mocking of interface

    private function createAlwaysTrueFeature(): FeatureManagerInterface
    {
        $feature = $this->createMock(FeatureManagerInterface::class);
        $feature->method('isActive')->with('foobar')->willReturn(true);

        return $feature;
    }

Some ideas

(new AlwaysTrueFeatureManager())->isActive();
(new AlwaysFalseFeatureManager())->isActive();
(new NamedTrueFeatureManager('foobar', 'foobar1'))->isActive('foobar');

Add correct env handling

env variables are resolved at runtime. In TreeBuilder and the DependencyInjection Extension we only have the hash value. As far as I read this is by design and will not change.

We have to add a possibility to set the feature active state via env variables.

See PR #12 for history.

[Add] Support roles

Add one standard role provider for active features.

Example:

# For one role
constraint: has_role('ROLE_ADMIN')

# For multiple roles
constraint: "has_role('ROLE_ADMIN') or has_role('ROLE_MOD')"

Strategy

Normally, the individual fields in the config.yml are an OR condition. In this example, the feature is enabled if the environment variable returns true or if the logged in user contains the ROLE_ADMIN role.

# config.yml

flagception:
    features:      
        feature_123:
            env: FOOBAR
            roles: ROLE_ADMIN

It would be interesting to be able to modify the strategy so that it becomes an AND condition. If you change the strategy and use the same example, the feature would only be enabled if the environment variable returns true AND the user contains the ROLE_ADMIN role.

# config.yml

flagception:
    features:      
        feature_123:
            env: FOOBAR
            roles: ROLE_ADMIN

        feature_345:
            env: FOOBAR
            roles: ROLE_ADMIN
            strategy: single # Overwrite the global strategy for this feature)
    
     # Set global for all (Default: single)            
     config:
         strategy: all

all => All defined conditions must match for activating this feature
single => at least one condition must match for activating this feature

Autowiring for Flagception\Manager\FeatureManagerInterface does not work as stated in the docs

This bundle is used in an PHP 7.3 / Symfony 4.4 application. There is a service which expects an Flagception\Manager\FeatureManagerInterface instance in the constructor:

use Flagception\Manager\FeatureManagerInterface;

// [...] 

/** @var FeatureManagerInterface */
private $featureManager;

public function __construct(FeatureManagerInterface $featureManager)
{
    $this->featureManager = $featureManager;
}

Symfony throws a RuntimeException now:

Cannot autowire service "App\Foo\Bar": argument "$featureManager" of method "__construct()" references interface "Flagception\Manager\FeatureManagerInterface" but no such service exists. You should maybe alias this interface to the existing "flagception.manager.feature_manager" service.

The documentation does not mention that I have to add the following entry in the services.yaml:

# [...]
Flagception\Manager\FeatureManagerInterface:
    alias: flagception.manager.feature_manager

# [...]

As soon as this addition has been added, the autowiring works as expected. Was it forgotten in the documentation or did I do something wrong?

[RFC] Support latest Symfony LTS in master branch

Last week I proposed PR #80 to allow checking for multiple features in route definition. The problem is that I need this in a Symfony 4.4 (LTS) project, so I proposed to merge the PR with the 3.x branch.

Once the PR was merged, a new 3.6.0 version was tagged and now the 3.x branch has more features that the master branch.

To avoid this, I think master branch should always support latest Symfony LTS version.

WDYT?

php8 support

Package requires php 5||7
PHP8 support need to be implemented

FeatureDataCollector should not be registered in kernel debug mode

After upgrading to version 4.3 which hides the TraceableDataCollector when APP_DEBUG=0 (#89), I now get the following error when running tests with debug mode disabled:

TypeError: Flagception\Bundle\FlagceptionBundle\Profiler\FeatureDataCollector::__construct(): Argument #1 ($chainActivator) must be of type Flagception\Bundle\FlagceptionBundle\Activator\TraceableChainActivator, Flagception\Activator\ChainActivator given

I think that maybe the FeatureDataCollector should not be registered when debug mode is disabled? Or perhaps it just needs the data_collector tag removed?

Environment Activator & Symfony 4.3+ "broken"

i updated my app from sf 3.4 to sf4.4 and my environment activators stopped working. this is because of symfony/symfony#31765

the DotEnv component get instanced differenlty in symfony 4.3 in the bootstrap.php file:

(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
for
(new Dotenv(true))->loadEnv(dirname(__DIR__).'/.env'); 

the true means that the variables of the .env files get "written" with putenv. this behavior was changed.

as flagception is using getenv() this change hit it.

the ticket is just for reference or maybe for a refactor to load and inject the variabled with %env()% (if possible).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.